CheckBox中的绑定似乎有问题。它抛出一个XamlParseException,并说双向绑定需要Path或XPath。以下是ContentPresenter进行评估。
<ContentPresenter Content="{Binding PropertyValue}">
<ContentPresenter.Resources>
<DataTemplate DataType="{x:Type System:String}">
<TextBox Text="{Binding}" MinWidth="100" MaxWidth="300"/>
</DataTemplate>
<DataTemplate DataType="{x:Type System:Boolean}">
<CheckBox IsChecked="{Binding}"/>
</DataTemplate>
</ContentPresenter.Resources>
</ContentPresenter>
我希望实现的是PropertyValue,它是一个多态对象,它的数据类型,相应的控件将在运行时创建。例如,如果PropertyValue是布尔属性,则控件将是一个复选框。如果用户切换复选框,则更改应反映在PropertyValue上。如果外部依赖项修改了PropertyValue(例如,INotifyPropertyChanged),则复选框也必须反映该更改。因此,我需要一种方法来实现双向绑定。
答案 0 :(得分:0)
错误非常精确......您不能双向绑定当前的DataContext
,而只能绑定>上下文中的属性。
<DataTemplate DataType="{x:Type ClassTypeContainingABoolean}">
<CheckBox IsChecked="{Binding YourBooleanProperty}"/>
</DataTemplate>
<DataTemplate DataType="{x:Type System:Boolean}">
<CheckBox IsChecked="{Binding Mode=OneWay}"/>
</DataTemplate>
取决于你真正想做的事情。
整件事与ContentPresenter
无关。
如果要在决定模板之前检查datacontext对象,可以使用TemplateSelector
。
public class MyTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
var elem = container as FrameworkElement;
if (item == null || elem == null)
{
return null;
}
var t = item.GetType();
var prop = t.GetProperty("PropertyValue");
if (prop == null)
{
return null;
}
// select template by the type of the PropertyValue parameter
if (typeof(bool?).IsAssignableFrom(prop.PropertyType))
{
return elem.FindResource("BooleanContextTemplate") as DataTemplate;
}
if (typeof(string).IsAssignableFrom(prop.PropertyType))
{
return elem.FindResource("StringContextTemplate") as DataTemplate;
}
return base.SelectTemplate(item, container);
}
}
数据上下文初始化,例如:
public class MyContextData<T>
{
public T PropertyValue { get; set; }
}
// initialize DataContext somewhere
private void Window_Loaded(object sender, RoutedEventArgs e)
{
grid1.DataContext = new MyContextData<bool>() { PropertyValue = true };
//grid1.DataContext = new MyContextData<string>() { PropertyValue = "ABC" };
}
Xaml示例:
<Window.Resources>
<local:MyTemplateSelector x:Key="MyContextDataTemplateSelector"/>
<DataTemplate x:Key="StringContextTemplate">
<TextBox Text="{Binding PropertyValue}" MinWidth="100" MaxWidth="300"/>
</DataTemplate>
<DataTemplate x:Key="BooleanContextTemplate">
<CheckBox IsChecked="{Binding PropertyValue}"/>
</DataTemplate>
</Window.Resources>
<Grid x:Name="grid1">
<ContentPresenter Content="{Binding}" ContentTemplateSelector="{StaticResource MyContextDataTemplateSelector}"/>
</Grid>
如您所见,模板选择器通过DataTemplate
引用的FindResource("BooleanContextTemplate")
需要在某处定义。 templateselector本身也是在资源中创建的,并传递给ContentPresenter.ContentTemplateSelector
属性。
请注意,ContentPresenter.Content
绑定不再定位YourBooleanProperty
,而此属性是模板的一部分。因此,最终,您的数据需要以某种确定性的方式包含在内,关于涉及的属性名称。