我正在构建一个可以编辑POCOs的控件。POCO中的字段有一个需要编辑的描述符集合,我正在将一个ListBox的ItemsSource绑定到这个集合中。除其他外,描述符使我能够选择一个合适的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>我遇到问题的是"TextTemplate“中的TextTemplate绑定表达式。问题是,"PathName“不应该被视为文字字符串,而是ColumnDescription类(用于ListBox.ItemsSource的ColumnCollection的集合类型)中字符串属性的名称,它给出了我要绑定到的POCO属性的名称( POCO是"vm.CurrentEditing")。
是否有办法将XAML中的属性值用作绑定表达式的输入,或者我将不得不求助于后面的代码?
(顺便说一句,正如我前面所做的那样,将ElementName指定为"x.y“似乎也是无效的。我想"y“部分应该在Path中,但是现在我的财产名是.!)
发布于 2016-06-28 18:49:56
因此,您希望将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和String DisplayPathName。它起作用了!当然,这取决于属性的任何类型的默认TextBox编辑行为。我认为这将获得与在XAML中显式绑定相同的结果,但它并不总是您想要的结果。但是,您可以非常容易地疯狂地在DataTemplate中添加一些触发器,以便在不同的编辑器中交换,或者编写一个DataTemplateSelector。
我把ViewModel.Foo塞进了一个ContentControl中,只是为了让一个DataTemplate出现,这样TextBox就能以与您相同的方式获得他的DataContext。
还请注意,我从DisplayPathName对象之外的某个相对源获得了DataContext --它不是Foo的成员,当然,它是视图模型的成员。
C#
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModel {
DisplayPathName = "Name",
Foo = new Foo { Name = "Aloysius" }
};
}XAML
<ContentControl
Content="{Binding Foo}"
>
<ContentControl.ContentTemplate>
<DataTemplate>
<TextBox
local:POCOWrangler.BindPropertyToText="{Binding
DataContext.DisplayPathName,
RelativeSource={RelativeSource AncestorType=ContentControl}}"
/>
</DataTemplate>
</ContentControl.ContentTemplate>
</ContentControl>这很有趣。
https://stackoverflow.com/questions/38082175
复制相似问题