WPF绑定ViewModel属性到附加属性

3

我的目标是创建一个添加文本属性到RichTextBox的功能。我创建了一个附加属性,并将其绑定到ViewModel的属性上。不幸的是,更改RichTextBox中的文本并不会更新底层属性。

这是我的代码:

View.cs:

public partial class KnuthMorrisPrattView : UserControl
{
    public KnuthMorrisPrattView()
    {
        InitializeComponent();
    }

    public static string GetText(DependencyObject obj)
    {
        return (string)obj.GetValue(TextProperty);
    }

    public static void SetText(DependencyObject obj, string value)
    {
        obj.SetValue(TextProperty, value);
    }

    public static readonly DependencyProperty TextProperty = DependencyProperty.RegisterAttached
    (
        "Text",
        typeof(string),
        typeof(KnuthMorrisPrattView),
        new FrameworkPropertyMetadata()
        {
            BindsTwoWayByDefault = true,
            PropertyChangedCallback = PropertyChangedCallback,
            CoerceValueCallback = CoerceValueCallback,
            DefaultUpdateSourceTrigger = UpdateSourceTrigger.LostFocus
        }
    );

    private static object CoerceValueCallback(DependencyObject dependencyObject, object baseValue)
    {
        throw new NotImplementedException();
    }

    private static void PropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
    {
        throw new NotImplementedException();
    }
}

View.xaml:

<UserControl x:Class="Launcher.Views.KnuthMorrisPrattView"
         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" 
         xmlns:views="clr-namespace:Launcher.Views"
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="500"
         DataContext="{Binding KnuthMorrisPrattViewModel, Source={StaticResource MainViewModel}}">
<Grid Margin="15">
    <Grid.RowDefinitions>
        <RowDefinition Height="7*"/>
        <RowDefinition Height="3*"/>
    </Grid.RowDefinitions>
    <DockPanel Grid.Row="0">
        <Label Content="Text" DockPanel.Dock="Top"></Label>
        <RichTextBox x:Name="TextBox" views:KnuthMorrisPrattView.Text="{Binding TextToSearchArg}"/>
    </DockPanel>
    <DockPanel Grid.Row="1">
        <Label Content="Pattern" DockPanel.Dock="Top"></Label>
        <TextBox Text="{Binding PatternArg}"/>
    </DockPanel>
</Grid>

ViewModel.cs:

using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using GalaSoft.MvvmLight.CommandWpf;
using Launcher.Runners.KnuthMorrisPratt;

namespace Launcher.ViewModels
{
    public class KnuthMorrisPrattViewModel : ViewModelBase
    {
        private string _textToSearchArg;
        private string _patternArg;

        public string TextToSearchArg
        {
            get { return _textToSearchArg; }
            set
            {
                _textToSearchArg = value;
                RaisePropertyChanged();
            }
        }

        public string PatternArg
        {
            get { return _patternArg; }
            set
            {
                _patternArg = value;
                RaisePropertyChanged();
            }
        }           

        public KnuthMorrisPrattViewModel()
        {

        }            
    }
}

我知道Callback会抛出异常,但我的目标只是在调试器下查看是否调用了这个回调函数。然后我添加正确的实现。
编辑: 我想我错过了关于我的问题的重要说明。当我从代码中更新TextToSearchArg属性时,一切都正常工作。唯一的问题是当我在RichTextBox中设置一些文本时,底层属性不会被更新。
我错过了什么?非常感谢。

抓取并监视UI绑定中正在发生的事情。 - user1228
@Will 你是什么意思? - Divh
你看过这篇文章吗?它描述了如何绑定RichTextBox内部的文本。希望能对你有所帮助 :) - sszarek
@Will Snoop在绑定方面没有显示任何错误。 此外,正如我在编辑部分中所写的那样。 当我以编程方式设置属性时,一切都正常工作,但是在RichTextbox中写入似乎没有任何效果。 - Divh
请问我在 FrameworkPropertyMetadata 中设置了 BindsTwoWayByDefault = true。我还尝试将 views: KnuthMorrisPrattView.Text=“{Binding TextToSearchArg,Mode = TwoWay}” 设为两向绑定,但都没有生效。 - Divh
显示剩余3条评论
2个回答

1

你的代码中没有显示Attached属性与RichTextBox事件绑定,因此如果RichTextBox中的内容/文本更改,它将永远不会被调用。

你需要订阅RichTextBox.TextChanged event

public partial class KnuthMorrisPrattView : UserControl
{
    public KnuthMorrisPrattView()
    {
        InitializeComponent();
        this.TextBox.TextChanged += OnTextChanged;
    }

    ...

    public void OnTextChanged(object sender, TextChangedEventArgs e) 
    {
        // Get the text from the event and set your Text Property 
        string text = ...; 
        SetText(this, text);
    }
}

编辑:

如果您想监听另一个控件的依赖/附加属性变化,请使用

DependencyPropertyDescriptor.FromProperty(ControlClassName.DesiredPropertyProperty, typeof(ControlClassName)).AddValueChanged(dependencyObject, OnDesiredPropertyChanged);

在此提醒:

您应该在视图中使用代码后端。并没有要求依赖属性或附加属性必须在同一类中定义,它们是为了其他类而定义的。

  • ControlClassName 是包含依赖属性的类(例如,在您的情况下是 RichTextBox 或定义依赖/附加属性的类)
  • 'DesiredPropertyProperty是您的属性名称(即TextProperty`
  • dependencyObject 是设置 DesiredPropertyProperty 的对象实例
  • OnDesiredPropertyChanged 方法在属性值更改时调用

0

可能

Mode=TwoWay, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged 

绑定丢失了吗?


你还没有将富文本框的文本属性绑定到任何东西上。 你需要绑定到 {Binding Text, RelativeSource={RelativeSource Self}}。 - Anthony Wieser
它不起作用是因为RichTextBox本身没有Text属性。我创建了一个叫做Text的附加属性,然后我想将其绑定到我的视图模型的Text属性上。正如我在上面的评论中所说,只有从RichTextBox到属性的绑定不起作用。当我以编程方式设置绑定属性时,RichTextBox会更新得很好。 - Divh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接