MVVM

2016-04-23 27 views
0

的属性更新withing我已经创建了一个基于MVVM 主窗口XAML的例子:MVVM

<UserControl x:Class="LearnMVVM.SomeUserControl" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:learnMvvm="clr-namespace:LearnMVVM" 
      xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase" 
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="300"> 
    <UserControl.DataContext> 
     <learnMvvm:SomeUserControlViewModel /> 
    </UserControl.DataContext> 
    <DockPanel> 
     <TextBox DockPanel.Dock="Top" Margin="10" Text="{Binding Path=A, Mode=TwoWay, diag:PresentationTraceSources.TraceLevel=High}" /> 
     <Label DockPanel.Dock="Top" Content="{Binding Path=Operation, diag:PresentationTraceSources.TraceLevel=High}" /> 
     <TextBox DockPanel.Dock="Top" Margin="10" Text="{Binding Path=B, Mode=TwoWay, diag:PresentationTraceSources.TraceLevel=High}" /> 
     <Button DockPanel.Dock="Top" Content="=" Margin="20" Command="{Binding CalculateOperationComamnd, Mode=TwoWay, diag:PresentationTraceSources.TraceLevel=High}" /> 
     <Label DockPanel.Dock="Top" Margin="10" Content="{Binding Path=Result, diag:PresentationTraceSources.TraceLevel=High}" /> 
    </DockPanel> 
</UserControl> 

视图模型的SomeCustomUserControl的:

using System; 
using System.ComponentModel; 
using System.Windows.Input; 

namespace LearnMVVM 
{ 
    public enum OperationType 
    { 
     Sum, 
     Sub, 
     Div, 
     Mul 
    } 

    public class SomeUserControlViewModel : INotifyPropertyChanged 
    { 
     public double A { get; set; } 
     public double B { get; set; } 

     //Команды 
     private ICommand calculateOperationCommand; 
     public ICommand CalculateOperationComamnd 
     { 
      get 
      { 
       return calculateOperationCommand; 
      } 
      set 
      { 
       if (calculateOperationCommand != value) 
       { 
        calculateOperationCommand = value; 
        OnPropertyChanged("CalculateOperationComamnd"); 
       } 
      } 
     } 

     private OperationType operation; 
     public OperationType Operation 
     { 
      get 
      { 
       return operation; 
      } 

      set 
      { 
       if (operation != value) 
       { 
        operation = value; 
        switch (operation) 
        { 
         case OperationType.Sum: 
          CalculateOperationComamnd = new RelayCommand(arg => OperationSum()); 
          break; 
         case OperationType.Sub: 
          CalculateOperationComamnd = new RelayCommand(arg => OperationSub()); 
          break; 
         case OperationType.Div: 
          CalculateOperationComamnd = new RelayCommand(arg => OperationDiv()); 
          break; 
         case OperationType.Mul: 
          CalculateOperationComamnd = new RelayCommand(arg => OperationMul()); 
          break; 
        } 
        OnPropertyChanged("Operation"); 
       } 
      } 
     } 

     private void OperationSum() 
     { 
      Result = A + B; 
     } 

     private void OperationSub() 
     { 
      Result = A - B; 
     } 

     private void OperationDiv() 
     { 
      Result = A/B; 
     } 

     private void OperationMul() 
     { 
      Result = A*B; 
     } 

     private double result; 
     public double Result 
     { 
      get { return result; } 
      set 
      { 
       if (Math.Abs(result - value) > 0.0001) 
       { 
        result = value; 
        OnPropertyChanged("Result"); 
       } 
      } 
     } 

     public event PropertyChangedEventHandler PropertyChanged; 
     protected virtual void OnPropertyChanged(string propertyName) 
     { 
      if (PropertyChanged != null) 
      { 
       PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
      } 
     } 

    } 
} 

<Window x:Class="LearnMVVM.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:local="clr-namespace:LearnMVVM" 
     xmlns:System="clr-namespace:System;assembly=mscorlib" 
     Title="MainWindow" Height="350" Width="525"> 
    <Window.DataContext> 
     <local:ViewModel /> 
    </Window.DataContext> 
    <Window.Resources> 
     <ObjectDataProvider x:Key="operationTypeEnum" MethodName="GetValues" ObjectType="{x:Type System:Enum}"> 
      <ObjectDataProvider.MethodParameters> 
       <x:Type TypeName="local:OperationType"/> 
      </ObjectDataProvider.MethodParameters> 
     </ObjectDataProvider> 
     <DataTemplate DataType="{x:Type local:SomeUserControlViewModel}"> 
      <local:SomeUserControl /> 
     </DataTemplate> 
    </Window.Resources> 
    <Grid> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition/> 
      <ColumnDefinition Width="25"/> 
      <ColumnDefinition/> 
      <ColumnDefinition/> 
      <ColumnDefinition/> 
     </Grid.ColumnDefinitions> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="25"/> 
      <RowDefinition Height="25"/> 
      <RowDefinition /> 
     </Grid.RowDefinitions> 
     <TextBox Grid.Column="0" Grid.Row="0" Margin="2" Text="{Binding Path=A, Mode=TwoWay}"/> 
     <TextBlock Grid.Column="1" Grid.Row="0" Text="+" TextAlignment="Center" VerticalAlignment="Center" Height="16" Margin="0,4,0,5"/> 
     <TextBox Grid.Column="2" Grid.Row="0" Margin="2" Text="{Binding Path=B, Mode=TwoWay}"/> 
     <Button Grid.Column="3" Grid.Row="0" Margin="2" Content="Посчитать" Command="{Binding ClickCommand}"/> 
     <TextBox Grid.Column="4" Grid.Row="0" Margin="2" IsReadOnly="True" Text="{Binding Path=Summa, Mode=TwoWay}"/> 

     <ComboBox Grid.Column="2" Grid.Row="1" SelectedItem="{Binding Path=SomeUserControl.Operation, Mode=TwoWay}" ItemsSource="{Binding Source={StaticResource operationTypeEnum}}" /> 
     <ContentControl Grid.Column="2" Grid.Row="2" BorderThickness="3" BorderBrush="Black" Content="{Binding Path=SomeUserControl}" /> 
    </Grid> 
</Window> 

的SomeUserControl的XAML

问题:自定义控件不会改变,当我从第e组合框和“计算”按钮不起作用。

实际上,SomeCustomControlViewModel中的所有属性都按预期更新,但在主窗口中没有效果。

我错过了什么吗?

回答

2

Operation不是SomeUserControl的财产。它是SomeUserControl的viewmodel的一个属性 - 可以作为控件的DataContext访问。尝试结合ComboBox.SelectedItem像这样:

SelectedItem="{Binding Path=SomeUserControl.DataContext.Operation, Mode=TwoWay}" 

的变化是,我加DataContext的路径。

这就是为什么你不使用视图模型与自定义控件,如果你真的想用它们作为控件。你编写一个派生自Control的控制类,并赋予它依赖属性。 Operation应该是从Control派生的类的依赖属性,而不是视图模型上的通知属性。然后通过应用ControlTemplate通过默认的Style来为其定义UI。

你在这里得到的是一个真正的儿童viewmodel。通过这种安排,通常父视图模型将提供子视图模型的一个实例,并将其绑定到子控件本身。那么任何想要使用子viewmodel属性的人都会绑定ChildVM.WhateverProperty

+0

谢谢!还有一个问题 - SomeUserControl被定义为SomeUserControlViewModel,我已将其更改为SomeUserControl,现在它按预期工作。 – Vadim