基于属性值更改WPF装饰器子级

时间:2016-08-22 14:44:35

标签: wpf mvvm

我有一个WPF控件,其内容完全取决于其数据上下文的属性。为此,我们只是说控件的DataContext是Product类型,其Status属性为InStock,OutOfStock或Discontinued。

我为每种状态类型都有单独的用户控件。我可以并且已经创建了某种面板,将每个面板的可见性绑定到Product.Status。但这会产生问题,因为一些用户控件最终会出现质朴的东西,因为有些依赖于所设置的各种属性。在我的实际应用中,有许多状态,因此visualtree对我来说太大了。

我通过创建问题解决了问题,在我的代码中,我检查了DataContext上的状态更改,并在一个大的switch语句中设置了相应的子代。如果可能的话,我想在XAML中这样做。我希望按需设置孩子,所以我假设我需要使用模板。像这样的东西: SwitchControl将派生自Decorator或Border,无论如何。

<SwitchControl Property="Status">
  <SwitchControl.Possibilities>
    <Possibility Value="Discontinued">
       <Possibility.Template>
            <DiscontinuedView />
       </Possibility.Template>
    </Possibility>
    <Possibility Value="InStock">
       <Possibility.Template>
            <InStockView />
       </Possibility.Template>
    </Possibility>
  <SwitchControl.Possibilities />
</SwitchControl>

如果我可以缩短整个事情,那就更好了:

<SwitchControl>
    <Possibility Value="Discontinued">
      <DiscontinuedView />
    </Possibility>
    <Possibility Value="InStock">
      <InStockView />
    </Possibility>
</SwitchControl>

重点是,在任何给定时间只存在一个孩子。有人知道如何完成这项工作吗?我环顾了MVVM框架,无法找到任何东西。否则,我将尝试自己创建一个自定义控件。

2 个答案:

答案 0 :(得分:0)

您可能需要查看DataTemplateSelector class。这允许您根据不同的标准定义模板,例如当前DataContext的类型。一个例子看起来有点如下:

public class MyDataTemplateSelector : DataTemplateSelector
{
            public DataTemplate DiscontinuedDataTemplate { get; set; }
    public DataTemplate InStockDataTemplate { get; set; }
    public DataTemplate OutOfStockDataTemplate { get; set; }

    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        var product = item as Product;
        switch (product.Status)
        {
            case Status.InStock:
                return InStockDataTemplate;
            case Status.Discontinued:
                return DiscontinuedDataTemplate;
            case Status.OutOfStock:
                return OutOfStockDataTemplate;
        }
        // Fallback
        return DiscontinuedDataTemplate;
    }
}

...并按以下方式使用它:

<Window.Resources>
    <DataTemplate x:Key="DiscontinuedDataTemplate">
       <DiscontinuedView />
    </DataTemplate>

    <DataTemplate x:Key="InStockDataTemplate">
       <InStockView />
    </DataTemplate>

    <DataTemplate x:Key="OutOfStockDataTemplate">
        <OutOfStockView />
    </DataTemplate>

    <!-- DataTemplate Selector -->
    <local:MyDataTemplateSelector x:Key="MyTemplateSelector"
          DiscontinuedDataTemplate="{StaticResource DiscontinuedDataTemplate}" 
          InStockDataTemplate="{StaticResource InStockDataTemplate}"
          OutOfStockDataTemplate="{StaticResource OutOfStockDataTemplate}"/>
</Window.Resources>

<ContentControl ContentTemplateSelector="{StaticResource MyTemplateSelector}" Content="{Binding Product}"/>

答案 1 :(得分:0)

感谢您的建议和回复。我最终创建了一个控件,我认为它可以更直接地解决问题。我一直在研究一个WPF帮助程序库,我将来会发布给nuget,但是如果你现在想要使用它,那就是:

https://gist.github.com/StevePotter/b17f8d4b2657a2d2610390a11fb57e03

包含示例XAML。我希望这对某人有用!