我查看有关执行DataTemplate的文章:
并根据属性类型关于DataTemplate:
我试图根据属性值显示具有不同控件的属性。我有这个部分工作的Xaml。我有两个问题:
该属性显示正确的控件,但是当我设置该值时,它不会返回该属性。意味着"设置"我的属性不是调用(但在我创建DataTemplate之前)。我发现设置属性的问题是关于=" {Binding Path =。}"但我无法找到解决方案来设置它。
此外,为了能够使其发挥作用,我必须"隔离"将Value转换为单个ViewModel,以便DataTemplate不会影响所有其他控件。
你能帮我找到更好的解决方案来解决这两个问题吗?
以下是与MyContainerViewModel链接的我的View的xaml代码,其中包含" ChangingDataType" :
<UserControl >
<UserControl.Resources>
<!-- DataTemplate for strings -->
<DataTemplate DataType="{x:Type sys:String}">
<TextBox Text="{Binding Path=.}" HorizontalAlignment="Stretch"/>
</DataTemplate>
<!-- DataTemplate for bool -->
<DataTemplate DataType="{x:Type sys:Boolean}">
<CheckBox IsChecked="{Binding Path=.}" />
</DataTemplate>
<!-- DataTemplate for Int32 -->
<DataTemplate DataType="{x:Type sys:Int32}">
<dxe:TextEdit Text="{Binding Path=.}" MinWidth="50" Mask="d" MaskType="Numeric" HorizontalAlignment="Stretch"/>
<!--<Slider Maximum="100" Minimum="0" Value="{Binding Path=.}" Width="100" />-->
</DataTemplate>
<!-- DataTemplate for decimals -->
<DataTemplate DataType="{x:Type sys:Decimal}">
<!-- <TextBox Text="{Binding Path=.}" MinWidth="50" HorizontalAlignment="Stretch" />-->
<dxe:TextEdit Text="{Binding Path=.}" MinWidth="50" Mask="f" MaskType="Numeric" HorizontalAlignment="Stretch" />
</DataTemplate>
<!-- DataTemplate for DateTimes -->
<DataTemplate DataType="{x:Type sys:DateTime}">
<DataTemplate.Resources>
<DataTemplate DataType="{x:Type sys:String}">
<TextBlock Text="{Binding Path=.}"/>
</DataTemplate>
</DataTemplate.Resources>
<DatePicker SelectedDate="{Binding Path=.}" HorizontalAlignment="Stretch"/>
</DataTemplate>
</UserControl.Resources>
<ContentPresenter Content="{Binding MyChangingPropery}"/>
</UserControl>
关于2的更多信息:
我希望在视图中包含根据对象而更改的标签和属性。像这样:
<UserControl>
<UserControl.Resources>
<!-- ...DataTemplate here... -->
</UserControl.Resources>
<StackPanel>
<Label Content="Allo"/>
<ContentPresenter Content="{Binding MyChangingPropery}"/>
</StackPanel>
</UserControl>
但是如果我将DataTemplate放在这个UserControl资源上,它也会影响Label&#34; allo&#34;。所以我不得不创建另一个包含DataTemplate和MyChangingProperty的视图,这样标签Allo就不会受到影响。但是为一个属性创建的额外View对我来说有点难看,我确信有更好的方法可以隔离DataTemplate,因此它只能应用于一个UIControl。
<UserControl >
<StackPanel>
<Label Content="Allo"/>
<ContentPresenter Content="{Binding MyContainerViewModel}"/>
</StackPanel>
</UserControl>
注意:此处的MyContainerViewModel与描述的第一个视图相关联。
提前致谢!
答案 0 :(得分:1)
一种可能的解决方案是使用DataTemplateSelector
。你不能使用双向绑定来绑定基本类型,因为这必须通过我认为WPF不支持的DataTemplate
以某种方式引用。
DataTemplateSelector
现在根据属性类型选择正确的DataTemplate
,并按名称在资源中搜索权限DataTemplate
。这也解决了您DataTemplates
与Label
进行互动的问题。
首先,您需要定义DataTemplateSelector
,根据属性的类型更改DataTemplate
:
public class MyDataTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
var fe = (FrameworkElement)container;
var prop = (item as MyViewModelType)?.MyChangingProperty;
if (prop is string)
return fe.FindResource("MyStringDT") as DataTemplate;
else if (prop is bool)
return fe.FindResource("MyBoolDT") as DataTemplate;
// More types...
return base.SelectTemplate(item, container);
}
}
然后你需要像这样更改UserControl
:
<UserControl>
<UserControl.Resources>
<local:MyDataTemplateSelector x:Key="MyDTSelector" />
<!-- DataTemplate for strings -->
<DataTemplate x:Key="MyStringDT">
<TextBox Text="{Binding MyChangingProperty, Mode=TwoWay}"
HorizontalAlignment="Stretch"/>
</DataTemplate>
<!-- DataTemplate for bool -->
<DataTemplate x:Key="MyBoolDT">
<CheckBox IsChecked="{Binding MyChangingProperty, Mode=TwoWay}" />
<!-- More DataTemplates... -->
</DataTemplate>
</UserControl.Resources>
<StackPanel>
<Label Content="Allo"/>
<ContentPresenter Content="{Binding MyContainerViewModel}"
ContentTemplateSelector="{StaticResource MyDTSelector}" />
</StackPanel>
</UserControl>
您可以找到有关DataTemplateSelector
here的更多信息。
您当然也可以在这个新DataType
上设置DataTemplates
,但这不是必需的,因为x:Key
无论如何都会使它们成为唯一。但如果你想,那么它必须是这样的:
<DataTemplate x:Key="MyStringDT" DataType="{x:Type local:MyViewModelType}">
答案 1 :(得分:0)
在我看来,之前发布的答案是矫枉过正的。虽然DateTemplateSelector
是一个有用的东西,但在这种情况下我似乎没有必要。
但是如果我将DataTemplate放在这个UserControl资源上,它也会影响Label&#34; allo&#34;。
它影响Label
对象的原因是Label
对象是ContentControl
,内容类型的模板匹配行为与您自己的ContentPresenter
相同}元素。并且您已将Label
对象的内容设置为string
值。但是你可以把你想要的任何东西作为它的内容。
修复不良影响的方法是通过将内容从string
对象更改为显式TextBlock
来拦截该行为(模板中的控件通常为string
对象获得分配)。例如:
<UserControl>
<UserControl.Resources>
<!-- ...DataTemplate here... -->
</UserControl.Resources>
<StackPanel>
<Label>
<TextBlock Text="Allo"/>
</Label>
<ContentPresenter Content="{Binding MyChangingPropery}"/>
</StackPanel>
</UserControl>
通过这种方式,您绕过了模板查找行为(因为TextBlock
没有映射到任何模板并且可以直接使用),而Label
的内容将只是带有您想要的文字的TextBlock
。
这似乎是解决问题的简单方法,而不是创建全新视图或添加DataTemplateSelector
。