我正在构建一个可以编辑POCO的控件。 POCO中的字段有一个描述符集合,需要进行编辑,我将ListBox
ItemsSource
绑定到此集合。除此之外,描述符使我能够在POCO中选择合适的DataTemplate
和变量名称,该ListBox
项应该编辑。
我的ListBox是这样构建的:
<ListBox ItemsSource="{Binding ColumnCollection, ElementName=root}">
<ListBox.Resources>
<DataTemplate x:Key="TextTemplate">
<StackPanel>
<TextBlock Text="{Binding DisplayName}" />
<!-- !!! Question about following line !!! -->
<TextBox Text="{Binding ElementName=vm.CurentEditing, Path=PathName}" />
</StackPanel>
</DataTemplate>
<!-- Details omitted for brevity -->
<DataTemplate x:Key="PickListTemplate" />
<DataTemplate x:Key="BooleanTemplate" />
</ListBox.Resources>
<ListBox.ItemTemplateSelector>
<local:DataTypeSelector
TextTemplate="{StaticResource TextTemplate}"
PickListTemplate="{StaticResource PickListTemplate}"
BooleanTemplate="{StaticResource BooleanTemplate}"
/>
</ListBox.ItemTemplateSelector>
</ListBox>
它是&#34; TextTemplate&#34;中的TextBox
绑定表达式。我遇到了问题。问题是&#34; PathName&#34;不应该被视为文字字符串,而是ColumnDescription
类中的字符串属性的名称(用于ColumnCollection
的集合类型ListBox.ItemsSource
),它给出了我要绑定的POCO属性(POCO是&#34; vm.CurrentEditing&#34;)。
有没有办法在XAML中使用属性的值作为绑定表达式的输入,还是我必须求助于代码?
(顺便说一下,将ElementName
指定为&#34; x.y&#34;正如我上面所做的那样似乎也是无效的。我认为&#34; y&#34;部分应该在Path
,但目前我的财产名称已被占用......!)
答案 0 :(得分:1)
因此,您希望将TextBox.Text
绑定到对象Y的属性X,其中X和Y都在运行时更改。
听起来你想做的事情类似于ListBox.DisplayMemberPath
:你可以将string
或PropertyPath
属性绑定到DisplayMemberPath
并且它可以正常工作。我这样做的方式是拥有类型为String
或PropertyPath
的依赖项属性,并以编程方式创建从该属性到任何属性的绑定。
所以,我写了一个附加属性,它创建了一个绑定。
public class POCOWrangler
{
#region POCOWrangler.BindPropertyToText Attached Property
public static String GetBindPropertyToText(TextBox obj)
{
return (String)obj.GetValue(BindPropertyToTextProperty);
}
public static void SetBindPropertyToText(TextBox obj, PropertyPath value)
{
obj.SetValue(BindPropertyToTextProperty, value);
}
public static readonly DependencyProperty BindPropertyToTextProperty =
DependencyProperty.RegisterAttached("BindPropertyToText", typeof(String), typeof(POCOWrangler),
new PropertyMetadata(null, BindPropertyToText_PropertyChanged));
private static void BindPropertyToText_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (e.NewValue is String && d is TextBox)
{
var tb = d as TextBox;
var binding = new Binding((String)e.NewValue);
// The POCO object we're editing must be the DataContext of the TextBox,
// which is what you've got already -- but don't set Source explicitly
// here. Leave it alone and Binding.Source will be updated as
// TextBox.DataContext changes. If you set it explicitly here, it's
// carved in stone. That's especially a problem if this attached
// property gets initialized before DataContext.
//binding.Source = tb.DataContext;
binding.Mode = BindingMode.TwoWay;
BindingOperations.SetBinding(tb, TextBox.TextProperty, binding);
}
}
#endregion POCOWrangler.BindPropertyToText Attached Property
}
我写了一个简单的例子:有一个名为Foo
的小类具有Name
属性,以及一个包含两个属性Foo Foo
和{{1}的视图模型}}。有用!当然,这取决于属性恰好是什么类型的默认String DisplayPathName
编辑行为。我认为这会得到与你在XAML中明确约束的结果相同的结果,但它并不总是一定只是你想要的。但你可以很容易地在TextBox
中添加一些触发器来交换不同的编辑器,或者写一个DataTemplate
。
我在DataTemplateSelector
填充ViewModel.Foo
只是为了获得ContentControl
行为,以便DataTemplate
以与TextBox
相同的方式获得DataContext
你的。
另请注意,我从DisplayPathName
对象之外的某个地方获取相对来源的DataContext
- 它不是{的成员{1}},当然,它是viewmodel的成员。
C#
Foo
XAML
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModel {
DisplayPathName = "Name",
Foo = new Foo { Name = "Aloysius" }
};
}
这很有趣。