Mar*_*ijn 5 c# wpf xaml binding datatemplate
我有一个绑定到项目列表的 ItemsControl。这些项目具有名称和值属性。value 属性属于 Object 类型,以允许使用不同的数据类型。为了正确显示 value 属性,我将 ContentPresenter 与我可能使用的每种数据类型的数据模板一起使用。
<ItemsControl ItemsSource="{Binding Items}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Path=Name}"/>
<GridSplitter Width="1"
Grid.RowSpan="4" Grid.Column="1"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
<ContentPresenter Grid.Column="2" Content="{Binding Value}">
<ContentPresenter.Resources>
<DataTemplate DataType="{x:Type System:String}">
<TextBox Text="{Binding Path=Content, RelativeSource={RelativeSource AncestorType={x:Type ContentPresenter}}}"
BorderThickness="0"/>
</DataTemplate>
<DataTemplate DataType="{x:Type System:Int32}">
<TextBox Text="{Binding Path=Content, RelativeSource={RelativeSource AncestorType={x:Type ContentPresenter}}}"
TextAlignment="Right"
BorderThickness="0"/>
</DataTemplate>
<DataTemplate DataType="{x:Type System:Double}">
<TextBox Text="{Binding Path=Content, RelativeSource={RelativeSource AncestorType={x:Type ContentPresenter}}}"
TextAlignment="Right"
BorderThickness="0"/>
</DataTemplate>
<DataTemplate DataType="{x:Type System:Boolean}">
<CheckBox IsChecked="{Binding Path=Content, RelativeSource={RelativeSource AncestorType={x:Type ContentPresenter}}}"
HorizontalAlignment="Center"/>
</DataTemplate>
</ContentPresenter.Resources>
</ContentPresenter>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Run Code Online (Sandbox Code Playgroud)
ContentPresenter 使用正确的数据类型并且效果很好。我的问题是编辑这些值对绑定的项目没有任何影响。我怀疑这是因为我绑定到 ContentPresenter 的内容属性而不是直接绑定到值。我试过像这样使用 ContentPresenter:
<ContentPresenter Grid.Column="2" Content="{Binding}">
<ContentPresenter.Resources>
<DataTemplate DataType="{x:Type System:String}">
<TextBox Text="{Binding Value}"
BorderThickness="0"/>
</DataTemplate>
Run Code Online (Sandbox Code Playgroud)
但是这样就不会选择正确的 DataTemplate 并且它只是显示对象而不是例如字符串。我还尝试像这样省略 DataTemplate 绑定中的路径:
<DataTemplate DataType="{x:Type System:String}">
<TextBox Text="{Binding}" BorderThickness="0"/>
</DataTemplate>
Run Code Online (Sandbox Code Playgroud)
有了这个,我得到一个异常,告诉我使用 Path 或 XPath 属性。
所以我的问题是:我如何正确绑定到 Value 以便它显示正确的 DataTemplate 并且对值的任何编辑都应用于绑定项目。
顺便说一句,由于某种原因,我的问题中的格式化代码块在第一行之后缩进了更多。我尝试修复它,但我不明白发生了什么。
我认为你会从阅读关于DataTemplates 中受益。首先,我建议您仔细阅读MSDN上的数据模板概述页面。正如我在我的评论中提到,你应该不使用ContentPresenter你DataTemplate秒。从链接页面:
您通常使用 ContentControl 的 ControlTemplate 中的 ContentPresenter 来指定要添加内容的位置。
你的东西似乎是丢失的是如何和什么将数据绑定到从里面一个DataTemplate。所述DataContext的DataTemplate将被自动设定为在所指定的类型的实例DataType属性。因此,DataTemplate可以访问的属性也将取决于DataType属性中指定的类型。例如,您不能这样做,因为 astring没有Value属性。
<DataTemplate DataType="{x:Type System:String}">
<TextBox Text="{Binding Value}" BorderThickness="0" />
</DataTemplate>
Run Code Online (Sandbox Code Playgroud)
相反,对于 a string,您需要DataContext像这样将数据绑定到整个值:
<DataTemplate DataType="{x:Type System:String}">
<TextBox Text="{Binding}" BorderThickness="0" />
</DataTemplate>
Run Code Online (Sandbox Code Playgroud)
或者,如果您有一个类名SomeClass并且该类有一个Value属性,那么您可以这样做:
<DataTemplate DataType="{x:Type YourDataTypesPrefix:SomeClass}">
<TextBox Text="{Binding Value}" BorderThickness="0"/>
</DataTemplate>
Run Code Online (Sandbox Code Playgroud)
现在,因为这些DataTemplates 是在没有设置它们的x:Key值的情况下定义的,所以DataTemplate只要框架看到相关类型的对象(并且没有设置其他显式模板),它就会自动呈现每个的内容。所以试试这个,如果你仍然有问题,请告诉我。
我已经对我的解决方案感到不舒服,我还遇到了无法将 List DataType 添加到 DataTemplates 的问题。我最终使用了一个 DataTemplateSelector,它产生了更好的代码。这里是:
内容控件。应用 DataTemplate 的数据的容器:
<ContentControl Grid.Column="2" Content="{Binding}"
ContentTemplateSelector="{StaticResource propertyItemTemplateSelector}">
</ContentControl>
Run Code Online (Sandbox Code Playgroud)
一些 DataTemplates 和 DataTemplateSelector 的声明:
<Style.Resources>
<local:PropertyTemplateSelector x:Key="propertyItemTemplateSelector"/>
<DataTemplate x:Key="dtStringValue">
<TextBox Text="{Binding Path=Value}"
BorderThickness="0"
IsReadOnly="{Binding Path=IsReadOnly}">
</TextBox>
</DataTemplate>
<DataTemplate x:Key="dtIntegerValue">
<TextBox Text="{Binding Path=Value}"
TextAlignment="Right"
BorderThickness="0"
IsReadOnly="{Binding Path=IsReadOnly}"/>
</DataTemplate>
...
Run Code Online (Sandbox Code Playgroud)
DataTemplateSelector 的代码:
public class PropertyTemplateSelector : DataTemplateSelector
{
public override System.Windows.DataTemplate SelectTemplate(object item, System.Windows.DependencyObject container)
{
DataTemplate template = null;
IPropertyItem propertyItem = item as IPropertyItem;
if (propertyItem != null)
{
FrameworkElement element = container as FrameworkElement;
if (element != null)
{
var value = propertyItem.Value;
if (value is String)
{
template = element.FindResource("dtStringValue") as DataTemplate;
}
else if (value is Int32)
{
template = element.FindResource("dtIntegerValue") as DataTemplate;
}
....
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
19875 次 |
| 最近记录: |