2013-12-11 2 views
1

У меня есть основной вид под названием MainContentView.xaml, в котором я установил DataContext в ViewModel под названием MainContentViewModel.cs. Здесь я могу обновить значения, которые появляются в пользовательском интерфейсе, так же, как нормальный MVVM будет работать.
Это выглядит следующим образом:Установить свойства в child UserControl текущего View с ViewModel (MVVM)

<UserControl x:Class="namespace:MyProject.View.Home.MainContentView" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:UserTools="clr-namespace:MyProject.View.Tools" 
      xmlns:ViewModel="clr-namespace:MyProject.ViewModel.Home" 
      mc:Ignorable="d" > 
    <UserControl.DataContext> 
     <ViewModel:MainContentViewModel /> 
    </UserControl.DataContext> 

    <Grid x:Name="mainGrid"> 
     <!-- Normal objects --> 
     <StackPanel> 
      <Label Text="Im a label" /> 
      <TextBox /> 
     </StackPanel> 
     <!-- My Custom Object --> 
     <UserTools:MyCustomUserControl x:Name="myUserControl" /> 
    </Grid> 
</UserControl> 

И мой MainContentViewModel.cs выглядит следующим образом:

public class MainContentViewModel : INotifyPropertyChanged { 
    public event PropertyChangedEventHandler PropertyChanged; 

    private string myLabel = ""; 
    public string MyLabel { 
     get { return this.myLabel; } 
     set { 
      this.myLabel = value; 
      OnPropertyChangedEvent("MyLabel"); 
     } 
    } 

    public MainContentViewModel() { 
     MyLabel = string.Format("my label text"); 
    } 

    protected virtual void OnPropertyChangedEvent(string _propertyName) { 
     var _handler = this.PropertyChanged; 
     if(_handler != null) { _handler(this, new PropertyChangedEventArgs(_propertyName)); } 
    } 
} 

Теперь я хочу установить некоторые свойства в MyCustomUserControl.xaml через его собственную MyCustomUserControlViewModel.cs.
Мои MyCustomUserControl.xaml выглядит следующим образом:

<UserControl x:Class="MyProject.View.Tools.MyCustomUserControl" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:ViewModel="clr-namespace:MyProject.ViewModel.Tools" 
      mc:Ignorable="d" > 
    <UserControl.DataContext> 
     <ViewModel:MyCustomUserControlViewModel /> 
    </UserControl.DataContext> 
    <Grid x:Name="mainGrid"> 
     <Label Content="{Binding myCustomLabel}" /> 
    </Grid> 
</UserControl> 

И мой MyCustomUserControlViewModel.cs выглядит следующим образом:

public class MyCustomUserControlViewModel : INotifyPropertyChanged { 
    public event PropertyChangedEventHandler PropertyChanged; 

    private string myCustomLabel = ""; 
    public string MyCustomLabel { 
     get { return this.myCustomLabel; } 
     set { 
      this.myCustomLabel = value; 
      OnPropertyChangedEvent("MyCustomLabel"); 
     } 
    } 

    public MyCustomUserControlViewModel() { 
     MyCustomLabel = string.Format("my custom label text"); 
    } 

    protected virtual void OnPropertyChangedEvent(string _propertyName) { 
     var _handler = this.PropertyChanged; 
     if(_handler != null) { _handler(this, new PropertyChangedEventArgs(_propertyName)); } 
    } 
} 

Теперь я хочу, из MainContentViewModel.cs, обновите MyCustomLabel недвижимости на MyUserCustomUserControl.xaml, и я полагаю, я нужно сделать это через MyCustomUserControlViewModel.cs, поэтому я могу сохранить шаблон MVVM.

Я пытался что-то вроде этого: В MainContentViewModel.cs

private MyCustomUserControlViewModel _viewModel = new MyCustomUserControlViewModel(); 
(...) 
public MainContentViewModel() { 
    (...) 
    _viewModel.SetMyCustomLabel("my new custom label text"); 
} 

И MyCustomUserControlViewModel.cs

public void SetMyCustomLabel(string _text) { 
    MyCustomLabel = _text; 
} 

Но это не работает. Я предполагаю, что это потому, что я создаю экземпляр другого объекта MyCustomUserControlViewModel.cs.

Итак, как я могу это сделать?


ОБНОВЛЕНО И РАБОЧАЯ (Спасибо Sheridan)
Я взял один из решений Шеридана и в конечном итоге с этим рабочим раствором. В моих MainContentView.xaml:

(...) 
<UserTools:MyCustomUserControl DataContext="{Binding ChildViewModel, Mode=OneWay}" /> 

В моих MainContentViewModel.cs:

private MyCustomUserControlViewModel childViewModel = new MyCustomUserControlViewModel(); 
public MyCustomUserControlViewModel ChildViewModel { 
    get { return childViewModel; } 
    private set { childViewModel = value; OnPropertyChangedEvent("ChildViewModel"); } 
} 

И тогда я могу это сделать:

public MainContentViewModel() { 
    (...) 
    ChildViewModel.SetMyCustomLabel("my new custom label text"); 
} 

ответ

2

Если вид модели родитель имел доступ к вид модели, например фактического ребенка (что, вероятно, не из-за того, как вы создаете экземпляр модели вашего ребенка), тогда вы могли бы просто сделать это:

public MainContentViewModel() { 
    (...) 
    _viewModel.CustomLabel = "my new custom label text"; 
} 

1.

Одно решение было бы удалить модель представления ребенка с точки зрения ребенка к модели родительского вида, а затем отобразить вид ребенка с помощью ContentControl и в DataTemplate:

<DataTemplate DataType="{x:Type ViewModels:MyCustomUserControlViewModel}"> 
    <Views:MyCustomUserControlView /> 
</DataTemplate> 

... 

В MainContentViewModel:

public MyCustomUserControlViewModel ChildViewModel 
{ 
    get { return childViewModel; } 
    private set { childViewModel = value; NotifyPropertyChanged("ChildViewModel"); } 
} 

... 

<Grid x:Name="mainGrid"> 
    <!-- Normal objects --> 
    <StackPanel> 
     <Label Text="Im a label" /> 
     <TextBox /> 
    </StackPanel> 
    <!-- My Custom Object --> 
    <ContentControl x:Name="myUserControl" Content="{Binding ChildViewModel}" /> 
</Grid> 

Выполнение этого действия позволит вам просто вызвать свойство, как показано в моем первом примере.

2.

Одним из вариантов было бы переместить свойство модели представления родителей и привязать к нему непосредственно от ребенка UserControl:

<Grid x:Name="mainGrid"> 
    <Label Content="{Binding DataContext.myCustomLabel, RelativeSource={RelativeSource 
     AncestorType={x:Type Views:MainContentView}}}" /> 
</Grid> 

UPDATE >>>

3.

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

<UserTools:MyCustomUserControl DataContext="{Binding ChildViewModel, 
Mode=OneWayToSource}" x:Name="myUserControl" /> 

Это просто догадываюсь, но может иметь возможность зацепиться модели представления ребенка, как это ... то вы могли бы сделать это в модели родительского вида:

if (ChildViewModel != null) ChildViewModel.CustomLabel = "my new custom label text"; 

4.

На самом деле ... У меня была другая идея. Вы могли бы сделать привязку от свойства в вашей модели представления родителя через к UserControl, если добавить к нему DependencyProperty:

<UserTools:MyCustomUserControl CustomLabel="{Binding CustomLabelInParentViewModel}" 
x:Name="myUserControl" /> 

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

+0

Когда вы указываете '' внутри DataTemplate, вы имеете в виду то же, что и 'x: Type ViewModels: MyCustom ...'? Кроме того, я не могу создать ChildViewModel в 'MainContentViewModel', как вы сказали. Что касается вашего последнего решения, я просто привел пример ярлыка в 'UserControl', объект намного сложнее, поэтому он отличается от' UserControl' и используется в нескольких местах. Это то, что я собрал из того, что вы сказали, по крайней мере. –

+0

К сожалению, это была ошибка копирования/вставки, которую я сейчас исправил. Префикс пространства имен «Views» XML является префиксом для ваших представлений. «DataTemplate» просто устанавливает экземпляр вашего представления для отображения, когда экземпляр вашей модели просмотра найден в пользовательском интерфейсе. – Sheridan

+0

Я понял, что вы говорили. Поэтому в основном я создаю «DataTemplate» дочернего представления с DataType моего дочернего ViewModel. Является ли объявление 'ChildViewModel' в' MainContentViewModel' правильным? И я полагаю, вам нужно связать его в представлении так: '', поэтому он не возвращает ошибку. –

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