2009-10-28 2 views
0

Я новичок в WPF и имею проблему с небольшим проектом. Я создаю тестер для имитации устройства, которое контролируется UDP. У меня есть пара классов, которые реализуют UDP как реализацию async. У меня был код главного окна, который обрабатывал буфер приема для данных и обновления. Он работал, но был очень неуклюжим. Поэтому я переместил весь код в async-получателе, где жил EndReceiveFrom. Это быстрее и избавляется от опроса. Но у меня больше нет доступа к элементам управления окнами для их обновления.Доступ к управлению WPF из класса, отличного от окна

Как я могу получить доступ к элементам управления извне окна? Окно создает экземпляр класса UDP, который запускает все это, поэтому я могу передавать объекты в вызове конструктора. У меня есть доступ, конечно, к App. Я знаю, что здесь что-то не хватает.

Ричард

+0

http://stackoverflow.com/questions/3373471/how-get-control-from-non-window-class-in-wpf – Eldar

ответ

2

был время, - так что я не буду предоставлять слишком много блоков коды - но звучит, как вы можете применить MVC, или его кузен MVP или MVVM. Не беспокойтесь о том, за что они стоят, но, вообще говоря, они пытаются определить отношения между View [вашим окном], данными [ваши результаты с сетевого уровня] и Business [ваш сетевой уровень].

В вашем случае я бы рекомендовал MVVM. Если вы Google, вы сможете найти множество информации о шаблоне проектирования и способах его применения. Опять же, не слишком суетитесь над теорией. Просто фью.

Далее, некоторые из мяса,

Концептуально, есть «данные» Вы хотите, чтобы представить в своем «вид». Не заботясь о представлении, давайте сначала инкапсулируем ваши данные.

// name is a little too general, so just rename it to something 
// specific in your source. 
public class NetworkViewModel 
{ 
    // enumerate your data here 
    public int Trouble { get; set; } 
    public int Tribbles { get; set; } 
    ... 
} 

Ваш взгляд на ваше окно. Имейте ваш взгляд создается экземпляр этой «модели представления»

public class MyNetworkMonitor 
{ 
    ... 
    // advanced: if you were injecting this - say from another source 
    // or intended to replace the instance during runtime, there are 
    // ways to deal with that. for now, we presume one instance for 
    // application lifetime. 
    public NetworkViewModel ViewModel { get; set; } 
    public MyNetworkMonitor() 
    { 
     ViewModel = new NetworkViewModel(); 
    } 
    ... 
} 

и в вашем Xaml, связываются со свойствами

// Xaml omitted, a limit to my memory :P 
// but just regular binding to say ViewModel.Trouble 

Хорошо. Поэтому, если ваша модель представления имеет начальное значение, она будет отображаться связанным элементом управления. К сожалению, если обновить свойства модели просмотра, невозможно определить связанный элемент управления, значение которого изменилось. Э-э, если, конечно, вы не реализуете общий интерфейс, который МОФ привязок искать,

public class NetworkViewModel : INotifyPropertyChanged 
{ 
    // defined by interface 
    public event PropertyChangedEventHandler PropertyChanged; 
    private int _trouble = 0; 
    public int Trouble 
    { 
     get { return _trouble; } 
     set 
     { 
      // 1. if value changes 
      if (_trouble != value) 
      { 
       _trouble = value; 
       // 2. inform whomever is listening! 
       if (PropertyChanged != null) 
       { 
        PropertyChanged (
         this, 
         new PropertyChangedEventArgs ("Trouble")); 
       } 
      } 
     } 
    } 
} 

Конечно, вы можете обернуть и делать все, что вы хотите, чтобы облегчить синтаксис, но то, что предшествует ваша реализация скелетных на модель сторона.

Если бы вы нажали кнопку, нажмите в своем окне и увеличьте ViewModel.Trouble, вы увидите обновление в режиме реального времени в связанном элементе управления. Ура!

Все, что осталось, это подключение вашего бизнес-уровня, то есть вашего сетевого уровня, к вашему ViewModel. Вы можете сделать это любым количеством способов. Вы можете передать экземпляр модели представления на свой сетевой уровень, вы можете заставить модель представления напрямую реагировать на события на сетевом уровне - это действительно полностью зависит от вас.

Теперь, если вы сделаете это, это не сработает. Сожалею. Теперь, это не совсем моя вина, вы видите, что Wpf не нравится, когда кто-либо модифицирует свои данные. Более конкретно, все, что может повлиять на управление Wpf , должно быть вызвано в потоке Gui, которому принадлежит элемент управления.Как вы можете догадаться, потоки, которые вы используете для изменения модели представления, происходят из сетевых перехватов и еще чего-то. Сетевые потоки. Pleabs. Morlocks. Pah!

В любом случае, я отвлекаюсь. Это относительно безболезненно. Когда вы обнаружите изменение, которое хотите сообщить, отправьте изменение в поток Gui.

someWpfControl.Dispatcher.Invoke (
    DispatcherPriority.Normal, 
    new Action(
    delegate() 
    { 
     ViewModel.Trouble = someNewValue; 
    }); 

но это бесполезно, поскольку ваш сетевой уровень не должен знать ничего о Wpf. Итак, как насчет в ViewModel

... 
// within property, after detecting change and 
// testing for listeners 
someWpfControl.Dispatcher.Invoke (
    DispatcherPriority.Normal, 
    new Action(
    delegate() 
    { 
     PropertyChanged (
      this, 
      new PropertyChangedEventArgs ("Trouble")); 
    }); 
... 

и то же, что и раньше, не стесняйтесь обертывать это где-нибудь еще. Как в вспомогательном методе. Btw, 'someWpfControl' может быть окном. Таким образом, вы можете передать его на ctor. Я также рекомендую вам альтернативы Google для «вызова диспетчера», поскольку могут быть более умные способы сделать это, чтобы не включать ссылки на управление, обширную резку и вставку в вашу модель представления или что-то еще.

Подобно тому, как долго, как нить Gui обновляет элемент управления, вы можете делать все, что вы хотите :)

Кроме того, бесстыдной плагин для моего партнера и МОФ Disciple Кента, который знает бесконечно больше о МОФ, чем я. [http://kentb.blogspot.com/]

Приветствия :)

+0

Btw, ваши лучшие ресурсы МОФ являются 1.) Google и 2.) Wpf Unleashed [книга]. Попробуй :) –

Смежные вопросы