在ContentControl中绑定null内容

时间:2016-10-17 09:30:48

标签: c# xaml uwp win-universal-app

我有ContentControl,我的DataTemplateSelector也支持null值。

<ContentControl Content="{x:Bind CurrentItem, Mode=OneWay}">
    <ContentControl.DataTemplateSelector>
        <my:DataTemplateSelector>
            <my:DataTemplateSelector.NullTemplate>
                <DataTemplate>
                    <Border Background="Red" />
                </DataTemplate>
            </my:DataTemplateSelector.NullTemplate>
            <my:DataTemplateSelector.CustomTemplate1>
                <DataTemplate>
                    <Border Background="Green" />
                </DataTemplate>
            </my:DataTemplateSelector.CustomTemplate1>
            <my:DataTemplateSelector.CustomTemplate2>
                <DataTemplate>
                    <Border Background="Blue" />
                </DataTemplate>
            </my:DataTemplateSelector.CustomTemplate2>
        </my:DataTemplateSelector>
    </ContentControl.DataTemplateSelector>                
</ContentControl>

问题是当CurrentItem变为null时,它不会调用DataTemplateSelector中的SelectTemplateCore方法。实际上只有在第一次加载控件且CurrentItem为空时才选择NullTemplate。

我可以用虚拟对象替换null值,但是处理这个问题要困难得多。 我找到了this解决方案,但它仅适用于WPF(UWP没有Style.Triggers)

1 个答案:

答案 0 :(得分:0)

我不确定你的ContentControl.DataTemplateSelector是什么,我想这是UWP中的ContentControl.ContentTemplateSelector

  

问题是当CurrentItem更改为null时,它不会调用DataTemplateSelector中的SelectTemplateCore方法。实际上只有在第一次加载控件且CurrentItem为空时才选择NullTemplate。

是的,你是对的。如果您稍后将CurrentItem设置为空,则TemplateSelector将不会再次遇到DataTemplateSelector。您需要的是为CurrentItem创建一个可为空的属性。例如:

<Page.Resources>
    <DataTemplate x:Key="NullTemplate">
        <Border Background="Red" Height="300" Width="300">
            <TextBlock Text="{Binding TemplateName}" />
        </Border>
    </DataTemplate>
    <DataTemplate x:Key="CustomTemplate1">
        <Border Background="Green" Height="300" Width="300">
            <TextBlock Text="{Binding TemplateName}" />
        </Border>
    </DataTemplate>
    <DataTemplate x:Key="CustomTemplate2">
        <Border Background="Blue" Height="300" Width="300">
            <TextBlock Text="{Binding TemplateName}" />
        </Border>
    </DataTemplate>
    <local:MyDataTemplateSelector x:Key="MyDataTemplateSelector"
                                  NullTemplate="{StaticResource NullTemplate}"
                                  CustomTemplate1="{StaticResource CustomTemplate1}"
                                  CustomTemplate2="{StaticResource CustomTemplate2}" />
</Page.Resources>

<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <ComboBox x:Name="combo" SelectionChanged="combo_SelectionChanged">
        <ComboBoxItem Content="NullTemplate" />
        <ComboBoxItem Content="CustomTemplate1" />
        <ComboBoxItem Content="CustomTemplate2" />
        <ComboBoxItem Content="SetCurrentItemToNull" />
        <ComboBoxItem Content="SetCurrentItemPropertyToNull" />
    </ComboBox>
    <ContentControl Content="{x:Bind CurrentItem, Mode=OneWay}" Margin="0,10"
                    ContentTemplateSelector="{StaticResource MyDataTemplateSelector}" />
</StackPanel>
代码背后的代码:

private ContentControlDataModel _CurrentItem;

public ContentControlDataModel CurrentItem
{
    get { return _CurrentItem; }
    set
    {
        if (value != _CurrentItem)
        {
            _CurrentItem = value;
            OnPropertyChanged();
        }
    }
}

public event PropertyChangedEventHandler PropertyChanged;

private void OnPropertyChanged([CallerMemberName]string propertyName = "")
{
    if (this.PropertyChanged != null)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

private void combo_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    var item = combo.SelectedItem as ComboBoxItem;
    switch (item.Content.ToString())
    {
        case "NullTemplate":
            CurrentItem = new ContentControlDataModel { Template = null, TemplateName = "NullTemplate" };
            break;

        case "CustomTemplate1":
            CurrentItem = new ContentControlDataModel { Template = true, TemplateName = "CustomTemplate1" };
            break;

        case "CustomTemplate2":
            CurrentItem = new ContentControlDataModel { Template = false, TemplateName = "CustomTemplate2" };
            break;

        case "SetCurrentItemToNull":
            CurrentItem = null;
            break;

        case "SetCurrentItemPropertyToNull":
            CurrentItem = new ContentControlDataModel { Template = null, TemplateName = null };
            break;

    }
}

ContentControlDataModel是这样的:

public class ContentControlDataModel
{
    public bool? Template { get; set; } //nullable property
    public string TemplateName { get; set; }
}

MyDataTemplateSelector

public class MyDataTemplateSelector : DataTemplateSelector
{
    public DataTemplate NullTemplate { get; set; }
    public DataTemplate CustomTemplate1 { get; set; }
    public DataTemplate CustomTemplate2 { get; set; }

    protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
    {
        var model = item as ContentControlDataModel;
        if (model == null || model.Template == null)
            return this.NullTemplate;
        else
        {
            return (bool)model.Template ? this.CustomTemplate1 : this.CustomTemplate2;
        }
    }
}

渲染图片:

enter image description here

您可以选择ComboBox的不同项目来检查差异。