我刚学会了创建自定义UserControls,我现在正在学习DataTemplates,仍然在学习属性,所以我可以想象控件属性的实现是错误的。
我已经开始创建名为ExtendedListBox
的UserControl,它可以使用复选框或普通列表框显示其项目。以下是ExtendedListBox
的实现。属性DisplayAs
用于选择要使用的DataTemplate。
我已经在StackOverflow上看了很多与DataTemplateSelectors相关的问题,它现在让我质疑这个实现,这应该由ContentControl完成吗? (见:Bind a property to DataTemplateSelector)
public partial class ExtendedListBox : UserControl
{
public ExtendedListBoxDisplay DisplayAs { get; set; }
public ExtendedListBox()
{
InitializeComponent();
}
}
以下是用户控件的xaml,DataTemplates在UserControl资源中作为CheckedListBoxTemplate和ListBoxTemplate
<UserControl x:Class="UserControlTest.Configuration.Controls.ExtendedListBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:enums="clr-UserControlTest.Configuration.Enums"
xmlns:local="clr-UserControlTest.Configuration.Controls"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:templateSelectors="clr-namespace:UserControlTest.Configuration.Controls.TemplateSelectors"
x:Name="UcExtendedListBox"
d:DesignHeight="84"
d:DesignWidth="100"
SizeChanged="ResizeControl"
mc:Ignorable="d">
<UserControl.Resources>
<ResourceDictionary>
<DataTemplate x:Key="CheckedListBoxTemplate" DataType="enums:ExtendedListBoxDisplay">
<CheckBox IsChecked="{Binding IsChecked}">
<TextBlock Text="{Binding}" TextWrapping="Wrap" />
</CheckBox>
</DataTemplate>
<DataTemplate x:Key="ListBoxTemplate" DataType="enums:ExtendedListBoxDisplay">
<TextBlock Text="{Binding}" TextWrapping="Wrap" />
</DataTemplate>
</ResourceDictionary>
</UserControl.Resources>
<ListBox x:Name="LstItems"
Grid.Row="2"
Width="{Binding ActualWidth,
ElementName=UcExtendedListBox}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
HorizontalContentAlignment="Center"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Visible"
SelectionChanged="RaiseSelectionChanged">
<ItemsControl>
<ItemsControl.ItemTemplateSelector>
<templateSelectors:ExtendedListBoxDataTemplateSelector
CheckedListBoxTemplate="{StaticResource CheckedListBoxTemplate}"
ListBoxTemplate="{StaticResource ListBoxTemplate}" />
</ItemsControl.ItemTemplateSelector>
</ItemsControl>
</ListBox>
</UserControl>
这是DataTemplateSelector,它的实现相当简单。
public class ExtendedListBoxDataTemplateSelector : DataTemplateSelector
{
public DataTemplate CheckedListBoxTemplate { get; set; }
public DataTemplate ListBoxTemplate { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (item == null)
{
return base.SelectTemplate(item, container);
}
var data = (ExtendedListBoxDisplay)item;
switch (data)
{
case ExtendedListBoxDisplay.CheckedListBox:
return CheckedListBoxTemplate;
case ExtendedListBoxDisplay.ListBox:
return ListBoxTemplate;
default:
return base.SelectTemplate(item, container);
}
}
}
所以我去运行它并且它不起作用,我猜它是因为我没有绑定项目和属性来寻找?作为DataTemplateSelectors的首次使用者,能不能指导我正确的方向?
非常感谢。
答案 0 :(得分:0)
您应该将ItemsSource
的{{1}}属性设置或绑定到ListBox
(或实际为IEnumerable<ExtendedListBoxDisplay>
):
IEnumerable<YourDataObject>
public partial class ExtendedListBox : UserControl
{
public ExtendedListBoxDisplay DisplayAs { get; set; }
public ExtendedListBox()
{
InitializeComponent();
LstItems.ItemsSource = new List<ExtendedListBoxDisplay>() { new ExtendedListBoxDisplay() };
}
}
集合中SelectTemplate
类的ExtendedListBoxDataTemplateSelector
方法将在ItemsSource
集合中的每个项目中调用一次,并且您返回的DataTemplate
将应用于此项目。
传递给方法的object
参数是对ItemsSource
中相应项的引用。
请注意,如果ExtendedListBoxDisplay
实际上是枚举,则应修改SelectTemplate
方法,并将ItemsSource
设置为其他类型。
答案 1 :(得分:0)
基本上你必须将枚举值设置为dataTemplate。希望这个链接有所帮助,它提供了一些如何做到这一点的见解。 DataTemplate in case of Enum 希望这会有所帮助。
答案 2 :(得分:0)
首先,当您指定DataType
的{{1}}时,您说该模板应仅应用于该类型的项目(或从该类型派生)。
因此,您需要做的第一件事就是从两个模板中删除DataTemplate
。
接下来,您需要修改模板选择器以使用绑定的DependancyObject而不是数据本身,因为您并不关心这些项目的数据类型。
E.g:
DataType="enums:ExtendedListBoxDisplay"
现在,我们现在期望该容器是public class ExtendedListBoxDataTemplateSelector : DataTemplateSelector
{
public DataTemplate CheckedListBoxTemplate { get; set; }
public DataTemplate ListBoxTemplate { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (container == null || !(container is ExtendedListBox))
{
return base.SelectTemplate(item, container);
}
var listBox = (ExtendedListBox)container;
switch (listBox.DisplayAs)
{
case ExtendedListBoxDisplay.CheckedListBox:
return CheckedListBoxTemplate;
case ExtendedListBoxDisplay.ListBox:
return ListBoxTemplate;
default:
return base.SelectTemplate(item, container);
}
}
}
,而不是期望该项成为ExtendedListBoxDisplay枚举。然后我们检查ExtendedListBox
的DisplayAs属性,并使用它来确定要显示的模板。