Itemselector项使用不同的datatemplates但应共享视图模型

时间:2017-08-18 17:51:52

标签: c# wpf

现在我正在使用具有三种不同数据模板,三种视图模型和一个itemtemplate选择器的自定义项控件。

一切正常,但我正在寻求改进此代码。以下是三个数据模板:

<DataTemplate x:Key="RefreshDevicesDataTemplate">
    <Grid Margin="5,0">
        <myApp:myAppButton Name="RefreshButton" Command="{Binding Command}" ToolTip="Refresh Devices" Style="{StaticResource TransparentStyle}">
            <Rectangle x:Name="RefreshRectangle" Width="20" Height="20" ToolTip="{Binding ToolTip}" Fill="{Binding IconBrush}" Opacity="1" Margin="0,0,0,6"/>
        </myApp:myAppButton>
    </Grid>
    <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding IsWaiting}" Value="True">
            <Setter Property="Opacity" Value="0.5" TargetName="RefreshRectangle" />
        </DataTrigger>                
    </DataTemplate.Triggers>
</DataTemplate>
<DataTemplate x:Key="DeviceDataTemplate">
    <Grid Margin="5,0">
        <Rectangle x:Name="IconRectangle" Width="20" Height="20" Fill="{Binding IconBrush}" Opacity="0.5" ToolTip="{Binding DeviceName}"/>
    </Grid>
    <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding IsConnected}" Value="True">
            <Setter Property="Opacity" Value="1" TargetName="IconRectangle" />
        </DataTrigger>
    </DataTemplate.Triggers>
</DataTemplate>
<DataTemplate x:Key="CommandDataTemplate">
    <Grid Margin="5,0">
        <myApp:myAppButton Style="{DynamicResource ChromelessButtonStyle}" Foreground="White" Content="{Binding CommandName, Converter={StaticResource LowerCaseConverter}}"
               Command="{Binding Command}" CommandParameter="{Binding CommandParameter}" ToolTip="{Binding ToolTip}"
               FontFamily="Marlett"/>
    </Grid>
</DataTemplate>

我的模板选择器:

<models:WindowCommandItemTemplateSelector x:Key="WindowCommandTemplateSelector" DeviceTemplate="{StaticResource DeviceDataTemplate}" CommandTemplate="{StaticResource CommandDataTemplate}" RefreshCommandTemplate="{StaticResource RefreshDevicesDataTemplate}"/>
public override DataTemplate SelectTemplate(object item, DependencyObject container) {

        DataTemplate resultTemplate = null;

        if (item is DeviceViewModel)
        {
            resultTemplate = DeviceTemplate;
        }
        else if (item is WindowCommandViewModel) // I need two view models because I can't know which template to use with just one class.
        {
            resultTemplate = CommandTemplate;
        }
        else if (item is RefreshCommandViewModel) // here too
        {
            resultTemplate = RefreshCommandTemplate;
        }

        return resultTemplate;
}

模板选择器只根据传入的视图模型选择模板。

最后我指定了我的itemscontrol:

<myApp:myAppWindow.WindowCommands>
    <myApp:WindowCommands ItemTemplateSelector="{StaticResource WindowCommandTemplateSelector}" ItemsSource="{Binding WindowCommands}" />
</myApp:myAppWindow.WindowCommands>

这是交易:我为每个数据模板设置了不同的视图模型,但实际上,RefreshButtonCommandDataTemplate只是具有不同模板的按钮。我有一些不同的绑定,例如IsWaiting,但那些只能在父视图模型中处理。

如果我想继续为这个itemscontrol添加自定义模板,那么视图模型和数据模板之间是否需要1-1对应?

也许我可以创建一些静态属性并检查它?是否有更多的WPF-y方式来做到这一点?我很陌生。感谢。

1 个答案:

答案 0 :(得分:1)

问题很混乱,但我认为您正试图避免创建多个viewmodel类型。使用DataTemplateSelector很容易,因为你可以执行你想要的任何逻辑。例如,您可以检查MySharedViewModel.Command的值并根据具体的命令返回模板。

  

如果我想继续为这个itemscontrol添加自定义模板,那么视图模型和数据模板之间是否需要1-1对应?

不,因为绑定在运行时按名称查找属性。您对Command的绑定将与RefreshCommandTemplate.CommandDeviceViewModel.Command匹配。

您唯一需要1:1映射的时间是使用DataTemplate.DataType属性,这是一个XAML快捷方式,可以避免创建DataTemplateSelector