Pan*_*nek 3 .net data-binding silverlight xaml expression-blend
我希望从datatemplate生成的元素看起来有所不同,具体取决于模型中的某些属性.例如,我希望以各种颜色显示文本,或者为每个生成的元素显示不同的图像或路径绘图.我知道如何一般地做到这一点,但我正在寻找一种解决方案,允许设计师在不触及代码的情况下编辑Expression Blend中的视觉细节.例如最简单的解决方案:
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="{Binding MyImageSource}"/>
<TextBlock Width="200" Text="{Binding MyText}" Forecolor="{Binding MyColor}"></TextBox>
</StackPanel>
</DataTemplate>
Run Code Online (Sandbox Code Playgroud)
其中'MyImageSource'和'MyColor'是项目模型(ImageSource和Brush类型)的属性,不能满足我的需求,因为我不想分配这些值.我希望设计师这样做.我的模型不是'MyImageSource'和'MyColor'属性,而是具有类型为enum或string(或其他类型)的'ItemType'或'ItemStyle'属性.我不是在寻找"宗教"MVVM的严格解决方案.我唯一的要求是避免设计师等待我按照他的指示纠正代码,例如"将列表Y中的X类型的项目颜色更改为#FFAACC",因为它似乎在某种程度上违反了SoC规则.
编辑(根据答案):
我找到了bendewey 在这里描述的类似解决方案- 它需要使用ItemsSource属性为控件派生自定义控件.为每种元素类型使用不同数据模板的想法很简洁,但在我看来,它涵盖了我们想要为每个项目生成完全不同的可视元素的情况.当元素仅在某些颜色和图像上有所不同(并且除此之外还包含许多常见元素),那么为每个元素类型创建单独的数据模板将导致不必要的代码(xaml)重复.在这种情况下,弗拉德的解决方案更适合.除了两个人之外还有其他技术吗?
您可以从WPF playbook中窃取ItemTemplateSelector概念.这就是这样:
<DataTemplate x:Key="MaleTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="M - " />
<TextBlock Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="FemaleTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="F - " />
<TextBlock Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
Run Code Online (Sandbox Code Playgroud)
<UserControl.Resources>
<local:PersonTemplateSelector x:Key="PersonTemplateSelector" />
</UserControl.Resources>
<Grid x:Name="LayoutRoot">
<local:CustomItemsControl ItemsSource="{Binding}" ItemTemplateSelector="{StaticResource PersonTemplateSelector}" />
</Grid>
Run Code Online (Sandbox Code Playgroud)
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
this.DataContext = Person.GetSampleData();
}
}
Run Code Online (Sandbox Code Playgroud)
public class PersonTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
var person = item as Person;
if (person != null)
{
switch (person.Gender)
{
case Gender.Male:
return Application.Current.Resources["MaleTemplate"] as DataTemplate;
case Gender.Female:
return Application.Current.Resources["FemaleTemplate"] as DataTemplate;
default:
throw new ArgumentOutOfRangeException();
}
}
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
如果这是因为你有兴趣使用它,你将需要使用这个CustomItemsControl,或一些变化:
public class CustomItemsControl : ItemsControl
{
public DataTemplateSelector ItemTemplateSelector
{
get { return (DataTemplateSelector)GetValue(ItemTemplateSelectorProperty); }
set { SetValue(ItemTemplateSelectorProperty, value); }
}
public static readonly DependencyProperty ItemTemplateSelectorProperty =
DependencyProperty.Register("ItemTemplateSelector", typeof(DataTemplateSelector), typeof(CustomItemsControl), new PropertyMetadata(null));
protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
{
ContentPresenter presenter = element as ContentPresenter;
if (presenter != null)
{
DataTemplate itemTemplate = null;
if (base.ItemTemplate != null)
{
itemTemplate = base.ItemTemplate;
}
else if (this.ItemTemplateSelector != null)
{
itemTemplate = this.ItemTemplateSelector.SelectTemplate(item, element);
}
presenter.Content = item;
presenter.ContentTemplate = itemTemplate;
}
}
}
public class DataTemplateSelector
{
public virtual DataTemplate SelectTemplate(object item, DependencyObject container)
{
return null;
}
}
Run Code Online (Sandbox Code Playgroud)