首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在XAML绑定表达式中使用变量

在XAML绑定表达式中使用变量
EN

Stack Overflow用户
提问于 2016-06-28 17:00:36
回答 1查看 1.3K关注 0票数 2

我正在构建一个可以编辑POCOs的控件。POCO中的字段有一个需要编辑的描述符集合,我正在将一个ListBoxItemsSource绑定到这个集合中。除其他外,描述符使我能够选择一个合适的DataTemplate和这个ListBox项应该编辑的变量名。

我的ListBox是这样构建的:

代码语言:javascript
复制
<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.ItemsSourceColumnCollection的集合类型)中字符串属性的名称,它给出了我要绑定到的POCO属性的名称( POCO是"vm.CurrentEditing")。

是否有办法将XAML中的属性值用作绑定表达式的输入,或者我将不得不求助于后面的代码?

(顺便说一句,正如我前面所做的那样,将ElementName指定为"x.y“似乎也是无效的。我想"y“部分应该在Path中,但是现在我的财产名是.!)

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-06-28 18:49:56

因此,您希望将TextBox.Text绑定到对象Y的属性X,其中X和Y在运行时都会更改。

听起来,您想要做的事情类似于ListBox.DisplayMemberPath:您可以将stringPropertyPath属性绑定到DisplayMemberPath,这样就可以工作了。我这样做的方式是有一个StringPropertyPath类型的依赖属性,并编程地从它创建一个绑定到任何属性。

因此,我编写了一个附加属性,它创建了一个绑定。

代码语言:javascript
复制
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 FooString DisplayPathName。它起作用了!当然,这取决于属性的任何类型的默认TextBox编辑行为。我认为这将获得与在XAML中显式绑定相同的结果,但它并不总是您想要的结果。但是,您可以非常容易地疯狂地在DataTemplate中添加一些触发器,以便在不同的编辑器中交换,或者编写一个DataTemplateSelector

我把ViewModel.Foo塞进了一个ContentControl中,只是为了让一个DataTemplate出现,这样TextBox就能以与您相同的方式获得他的DataContext

还请注意,我从DisplayPathName对象之外的某个相对源获得了DataContext --它不是Foo的成员,当然,它是视图模型的成员。

C#

代码语言:javascript
复制
public MainWindow()
{
    InitializeComponent();

    DataContext = new ViewModel { 
            DisplayPathName = "Name",
            Foo = new Foo { Name = "Aloysius" }
        };
}

XAML

代码语言:javascript
复制
<ContentControl
    Content="{Binding Foo}"
    >
    <ContentControl.ContentTemplate>
        <DataTemplate>
            <TextBox
                local:POCOWrangler.BindPropertyToText="{Binding 
                    DataContext.DisplayPathName, 
                    RelativeSource={RelativeSource AncestorType=ContentControl}}"
                />
        </DataTemplate>
    </ContentControl.ContentTemplate>
</ContentControl>

这很有趣。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38082175

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档