2015-09-08 67 views
0

我有一个基于MVVM的WPF应用程序。 它可以设置参数。参数可以是复选框中的字符串列表或numupdown中的双精度值。每个设备都有自己的参数,因此参数是动态加载的。这就是为什么我使用DataTemplateSelector。绑定未更新DataTemplateSelector

XAML代码

<ItemsControl ItemsSource="{Binding ParameterWrapperList}" ItemTemplateSelector="{StaticResource propertyDataTemplateSelector}"> 
    <ItemsControl.ItemsPanel> 
     <ItemsPanelTemplate> 
     <StackPanel Orientation="Horizontal"></StackPanel> 
     </ItemsPanelTemplate> 
    </ItemsControl.ItemsPanel> 
</ItemsControl> 

的模板是一个资源字典:

<DataTemplate x:Key="doubleTemplate"> 
 
     <Grid Visibility="{Binding Parameter.ParameterModel.IsVisible, Converter={StaticResource Visibility}}"> 
 
      <Grid.RowDefinitions> 
 
       <RowDefinition Height="{Binding Path=RowHeight, Mode=OneWay}"/> 
 
       <RowDefinition/> 
 
      </Grid.RowDefinitions> 
 
      <Border Grid.Row="0" Style="{StaticResource HeaderBorderStyle}" Width="{Binding Width}" Visibility="{Binding HeaderVisibility, Converter={StaticResource Visibility}}"> 
 
       <StackPanel Orientation="Horizontal"> 
 
        <Label Content="{Binding Parameter.DisplayName}"/> 
 
       </StackPanel> 
 
      </Border> 
 
      <Border Grid.Row="1" Style="{StaticResource ItemBorderStyle}" Width="{Binding Width}">     
 
       <telerik:RadNumericUpDown Name="nudParameterValue" Value="{Binding Path=ParameterValue, Mode=TwoWay}" Minimum="{Binding Parameter.ParameterModel.MinimumValue}" Maximum="{Binding Parameter.ParameterModel.MaximumValue}" NumberDecimalDigits="{Binding Parameter.ParameterModel.NumberDecimalDigits}" SmallChange="{Binding Parameter.ParameterModel.SmallChanges}"/>         
 
      </Border> 
 
     </Grid> 
 
    </DataTemplate> 
 
    <DataTemplate x:Key="stringTemplate"> 
 
     <Grid Visibility="{Binding Parameter.ParameterModel.IsVisible, Converter={StaticResource Visibility}}"> 
 
      <Grid.RowDefinitions> 
 
       <RowDefinition Height="{Binding Path=RowHeight, Mode=OneWay}"/> 
 
       <RowDefinition/> 
 
      </Grid.RowDefinitions> 
 
      <Border Grid.Row="0" Style="{StaticResource HeaderBorderStyle}" Width="{Binding Width}" Visibility="{Binding Path=HeaderVisibility, Converter={StaticResource Visibility}}"> 
 
       <Label Content="{Binding Parameter.DisplayName}"/> 
 
      </Border> 
 
      <Border Grid.Row="1" Style="{StaticResource ItemBorderStyle}" Width="{Binding Width}" > 
 
       <ComboBox ItemsSource="{Binding Path=Parameter.ParameterModel.PossibleValues}" SelectedIndex="{Binding ParameterValue, Mode=TwoWay}"> 
 

 
       </ComboBox> 
 
      </Border> 
 
     </Grid> 
 
    </DataTemplate> 
 
    <configControl:PropertyDataTemplateSelector 
 
      StringTemplate="{StaticResource stringTemplate}" 
 
      DoubleTemplate="{StaticResource doubleTemplate}" 
 
      x:Key="propertyDataTemplateSelector"/>

我写的代码为DataTemplateSelector。

public class PropertyDataTemplateSelector : DataTemplateSelector 
{ 
    public DataTemplate DoubleTemplate { get; set; } 
    public DataTemplate StringTemplate { get; set; } 

    public override DataTemplate SelectTemplate(object item, 
       DependencyObject container) 
    { 
     DeviceModel.ParameterType devFunct = ((ParameterWrapper)item).Parameter.ParameterModel.Type; 
     switch (devFunct) 
     { 
      case DeviceModel.ParameterType.Double: 
       return DoubleTemplate; 
      case DeviceModel.ParameterType.String: 
       return StringTemplate; 
      default: 
       return null; 
     } 
     return null;    
    } 
} 

当应用程序打开时,所有的值都设置正确。但是当我更新ParameterValue时,它不会更新视图。 (当我在控制台窗口中输出值时,值设置正确(但不在GUI中))。

我该怎么做才能做到这一点。

编辑

这是它绑定到的代码。每个功能都有一个复选框,当您更改参数时,所有其他检查的参数都需要更改。

 public double ParameterValue 
    { 
     get 
     { 
      return _parameter.ParameterValue; 
     } 
     set 
     { 
      Parameter.ParameterValue = value; 
      Console.WriteLine("ParameterValueChanged"); 
      if (SetOthers) 
      { 
       if (_parentFunction.Checked) 
       { 
        foreach (var function in _parentFunction.FunctionWrapperList) 
        { 
         if (function.Checked) 
         { 
          foreach (var parameterWrapper in function.ParameterWrapperList) 
          { 
           if (parameterWrapper.Parameter != this.Parameter) 
           { 
            if (parameterWrapper.Parameter.ParameterModel == Parameter.ParameterModel) 
            { 
             Console.WriteLine(function.Function.Name + " " + function.Checked + " " + Parameter.ParameterValue); 
             parameterWrapper.SetValue(Parameter.ParameterValue); 
            } 
           } 
          } 
         } 
        } 
       } 
      } 
      Notify("ParameterValue"); 
     } 
    } 

    private void SetValue(double parameterValue) 
    { 
     SetOthers = false; 
     Parameter.ParameterValue = parameterValue; 
     SetOthers = true; 
    } 

布尔SetOthers是,所以他不会得到一个计算器并保持设置本身。

+0

我看到你一切绑定到你的模型层。这在MVVM中并不常见,绑定应该以ViewModel层为目标。你在模型中实现INotifyPropertyChanged吗? – nkoniishvt

+0

@nkoniishvt它绑定在ViewModel图层上。我使用INotifyPropertyChanged。问题是,当我不使用DataTemplateSelector时,MVVM和绑定工作。但是当使用数据模板选择器时,这些值不会在GUI中更新。 – Gulpener

+1

我们需要更多的代码,例如您的视图模型 – nkoniishvt

回答

0

您的DataTemplateSelector不会更新DataTemplate呈现您的数据,因为DataTemplateSelector不会触发属性更改。它只根据类型(yourData.GetType())选择一种显示数据的方式。

你想要的是一个触发:

<ItemsControl ItemsSource="{Binding ParameterWrapperList}"> 
    <ItemsControl.ItemTemplate> 
     <DataTemplate> 
      <ContentControl Content="{Binding}"> 
       <ContentControl.Style> 
        <Style TargetType="{x:Type ContentControl}"> 
         <Setter Property="ContentTemplate" Value="{StaticResource doubleTemplate}"/> 
         <Style.Triggers> 
          <DataTrigger Binding="{Binding Parameter.ParameterModel.Type}" Value="{x:Static local:DeviceModel.ParameterType.String}"> 
           <Setter Property="ContentTemplate" Value="{StaticResource stringTemplate}"/> 
          </DataTrigger> 
         </Style.Triggers> 
        </Style> 
       </ContentControl.Style> 
      </ContentControl> 
     </DataTemplate> 
    </ItemsControl.ItemTemplate> 
    <ItemsControl.ItemsPanel> 
     <ItemsPanelTemplate> 
     <StackPanel Orientation="Horizontal"/> 
     </ItemsPanelTemplate> 
    </ItemsControl.ItemsPanel> 
</ItemsControl> 
+0

我收到错误:ItemTemplate不支持'ContentControl'类型的值。 – Gulpener

+0

取得进展,认为你忘记了ItemsControl.ItemTemplate和ContentControl之间的DataTemplate。 – Gulpener

+0

我得到了这个工作,但仍然MVVM坏了。我希望它与DataTemplateSelector有关。 – Gulpener