DependencyProperty ...可以设置,但无法通过绑定获取值

发布于 2024-12-09 10:22:54 字数 4300 浏览 0 评论 0原文

我有一个窗口,其中包含一个用户控件“TemplateEditor”。 (缩短的)TemplateEditor XAML 是:

<UserControl x:Class="xxx.Windows.Core.Controls.TemplateEditor"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             x:Name="userControl">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <TextBox Grid.Row="1" x:Name="textBox" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" />
    </Grid>
</UserControl>

我希望能够通过 TemplateEditor 将数据绑定到文本框“textBox”中。我使用 DependencyProperty 来屏蔽代码隐藏中的 TextBox:

namespace xxx.Windows.Core.Controls
{
    public partial class TemplateEditor : UserControl 
    {
        public string Text
        {
            get 
            { 
                string s=(string)GetValue(TextProperty);
                return s;
            }
            set 
            {
                if (Text != value)
                { 
                    SetValue(TextProperty, value);
                }
            }
        }

        public static readonly DependencyProperty TextProperty =
            DependencyProperty.Register("Text", typeof(string), typeof(TemplateEditor),new PropertyMetadata(null,Text_PropertyChanged));

        public TemplateEditor()
        {
            InitializeComponent();
        }

        private static void Text_PropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
        {
            ((TemplateEditor)source).textBox.Text = (string)e.NewValue;
        } 
    }
}

因此,您可以看到我有一个 DependencyProperty Text,我有一个回调来拾取对绑定所做的更改(例如,来自 ViewModel)和适用于文本框值。

这有效。

问题是,我似乎无法反向进行绑定工作,即。将值从 Text 属性(以及 TextBox)中取回并返回到绑定使用者(ViewModel)。我已经调试了调用 GetValue(TextProperty) ,这会返回正确的值,因此 DP 字典会正确更新。

在父窗口的 XAML 中给出以下绑定:

<src:ApplicationWindowBase x:Class="xxx.Windows.Client.Filing"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:src="clr-namespace:xxx.Windows.Core;assembly=MIGTurbo1.Windows.Core"
        xmlns:viewmodel="clr-namespace:xxx.Windows.Client.ViewModel"
        xmlns:converters="clr-namespace:xxx.Windows.Client.Converters"
        xmlns:xxx_Windows_Core_Controls="clr-namespace:xxx.Windows.Core.Controls;assembly=xxx.Windows.Core" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
        mc:Ignorable="d" 
        Title="File Item(s)" Height="450" Width="550" ShowInTaskbar="False">
    <src:ApplicationWindowBase.Resources>
        <viewmodel:ViewModelLocator x:Key="ViewModelLocator" d:IsDataSource="True"/>
        <converters:FileableItemNameStringConverter x:Key="fileableItemNameStringConverter" />
        <converters:FileableItemTypeStringConverter x:Key="fileableItemTypeStringConverter" />
        <converters:FileableItemMetaDataStringConverter x:Key="fileableItemMetaDataStringConverter" />
        <converters:FileableItemIconConverter x:Key="fileableItemIconConverter" />
    </src:ApplicationWindowBase.Resources>
    <src:ApplicationWindowBase.DataContext>
        <Binding Mode="OneWay" Path="Filing" Source="{StaticResource ViewModelLocator}"/>
    </src:ApplicationWindowBase.DataContext>
    <Grid>
       <!-- SNIP -->
    <xxx_Windows_Core_Controls:TemplateEditor Grid.Column="1" Grid.Row="1" Margin="0" Text="{Binding Comment, Mode=TwoWay}" d:LayoutOverrides="Width, Height"/>
       <!-- SNIP -->
</src:ApplicationWindowBase>

我正在使用 MVVM Light 并且 ViewModel 确实绑定正确。还有其他可以正常工作的控件/字段绑定(已省略)。问题是 Comment ViewModel 属性上的 Text 属性绑定不起作用。我可以很好地设置它(即在 ViewModel 中设置值,然后绑定),但用户在 Text 中输入的值永远不会进入 ViewModel Comments 属性。

我做错了什么?

I have a Window, containing a UserControl 'TemplateEditor'. The (shortened) TemplateEditor XAML is:

<UserControl x:Class="xxx.Windows.Core.Controls.TemplateEditor"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             x:Name="userControl">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <TextBox Grid.Row="1" x:Name="textBox" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" />
    </Grid>
</UserControl>

I want to be able to bind data through the TemplateEditor into the TextBox "textBox". I'm using a DependencyProperty to mask the TextBox in the code-behind:

namespace xxx.Windows.Core.Controls
{
    public partial class TemplateEditor : UserControl 
    {
        public string Text
        {
            get 
            { 
                string s=(string)GetValue(TextProperty);
                return s;
            }
            set 
            {
                if (Text != value)
                { 
                    SetValue(TextProperty, value);
                }
            }
        }

        public static readonly DependencyProperty TextProperty =
            DependencyProperty.Register("Text", typeof(string), typeof(TemplateEditor),new PropertyMetadata(null,Text_PropertyChanged));

        public TemplateEditor()
        {
            InitializeComponent();
        }

        private static void Text_PropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
        {
            ((TemplateEditor)source).textBox.Text = (string)e.NewValue;
        } 
    }
}

So from that you can see I have a DependencyProperty Text that I have a callback on to pick up changes made by to the binding (say, from the ViewModel) and apply to the TextBox value.

This works.

The problem is, I can't seem to have the binding work in reverse, ie. to get the value back out of the Text property (and therefore the TextBox) and back in to the binding consumer (the ViewModel). I've debugged calling GetValue(TextProperty) and this returns the correct value so the DP dictionary is correctly updating.

Given the following Binding in the parent Window's XAML:

<src:ApplicationWindowBase x:Class="xxx.Windows.Client.Filing"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:src="clr-namespace:xxx.Windows.Core;assembly=MIGTurbo1.Windows.Core"
        xmlns:viewmodel="clr-namespace:xxx.Windows.Client.ViewModel"
        xmlns:converters="clr-namespace:xxx.Windows.Client.Converters"
        xmlns:xxx_Windows_Core_Controls="clr-namespace:xxx.Windows.Core.Controls;assembly=xxx.Windows.Core" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
        mc:Ignorable="d" 
        Title="File Item(s)" Height="450" Width="550" ShowInTaskbar="False">
    <src:ApplicationWindowBase.Resources>
        <viewmodel:ViewModelLocator x:Key="ViewModelLocator" d:IsDataSource="True"/>
        <converters:FileableItemNameStringConverter x:Key="fileableItemNameStringConverter" />
        <converters:FileableItemTypeStringConverter x:Key="fileableItemTypeStringConverter" />
        <converters:FileableItemMetaDataStringConverter x:Key="fileableItemMetaDataStringConverter" />
        <converters:FileableItemIconConverter x:Key="fileableItemIconConverter" />
    </src:ApplicationWindowBase.Resources>
    <src:ApplicationWindowBase.DataContext>
        <Binding Mode="OneWay" Path="Filing" Source="{StaticResource ViewModelLocator}"/>
    </src:ApplicationWindowBase.DataContext>
    <Grid>
       <!-- SNIP -->
    <xxx_Windows_Core_Controls:TemplateEditor Grid.Column="1" Grid.Row="1" Margin="0" Text="{Binding Comment, Mode=TwoWay}" d:LayoutOverrides="Width, Height"/>
       <!-- SNIP -->
</src:ApplicationWindowBase>

I am using MVVM Light and the ViewModel does bind correctly. There are other control/field bindings (ommitted) that work fine. THe problem is that the Text property binding on the Comment ViewModel property is not working. I can set it fine (ie. set value in ViewModel, then bind) but the user-entered value in Text never goes into the ViewModel Comments property.

What am I doing wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

心碎无痕… 2024-12-16 10:22:54

试试这个:

<TextBox Text="{Binding ElementName=userControl,Path=Text,Mode=TwoWay}" />

并删除处理程序。

Try this:

<TextBox Text="{Binding ElementName=userControl,Path=Text,Mode=TwoWay}" />

and remove handlers.

暖树树初阳… 2024-12-16 10:22:54

好的,采用了典型的 StackOverflow 使用模式

我意识到我正在编写这个单向,添加了一个 TextChanged 事件处理程序来更新依赖项属性。

public partial class TemplateEditor : UserControl 
{

    public string Text
    {
        get 
        { 
            string s=(string)GetValue(TextProperty);
            return s;
        }
        set 
        {
            if (Text != value)
            { 
                SetValue(TextProperty, value);
            }
        }
    }

    public static readonly DependencyProperty TextProperty =
        DependencyProperty.Register("Text", typeof(string), typeof(TemplateEditor),new PropertyMetadata(null,Text_PropertyChanged));

    public TemplateEditor()
    {
        InitializeComponent();

        textBox.TextChanged += new TextChangedEventHandler(textBox_TextChanged);
    }

    private static void Text_PropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
    {
        ((TemplateEditor)source).textBox.Text = (string)e.NewValue;
    }


    void textBox_TextChanged(object sender, TextChangedEventArgs e)
    {
        Text = textBox.Text;
    }
}

感谢您抽出时间,并表示歉意。 :)

Ok, typical StackOverflow usage pattern adopted.

I realised I am writing this one-way, have added a TextChanged event handler to update the dependency property.

public partial class TemplateEditor : UserControl 
{

    public string Text
    {
        get 
        { 
            string s=(string)GetValue(TextProperty);
            return s;
        }
        set 
        {
            if (Text != value)
            { 
                SetValue(TextProperty, value);
            }
        }
    }

    public static readonly DependencyProperty TextProperty =
        DependencyProperty.Register("Text", typeof(string), typeof(TemplateEditor),new PropertyMetadata(null,Text_PropertyChanged));

    public TemplateEditor()
    {
        InitializeComponent();

        textBox.TextChanged += new TextChangedEventHandler(textBox_TextChanged);
    }

    private static void Text_PropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
    {
        ((TemplateEditor)source).textBox.Text = (string)e.NewValue;
    }


    void textBox_TextChanged(object sender, TextChangedEventArgs e)
    {
        Text = textBox.Text;
    }
}

Thanks for your time, and apologies. :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文