繁体   English   中英

在ContentControl中绑定null内容

[英]Binding null Content in ContentControl

我有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值,但是处理这个问题要困难得多。 我找到了这个解决方案,但它仅适用于WPF(UWP没有Style.Triggers)

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

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

是的,你是对的。 当您稍后将CurrentItem设置为null时, 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;
        }
    }
}

渲染图像:

在此输入图像描述

您可以通过选择ComboBox不同项来检查差异。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM