MVVM

2016-04-23 52 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