SetBinding未注册PropertyChanged事件

时间:2015-07-23 17:18:55

标签: c# xaml binding propertychanged

在我正在处理的应用程序中,我以编程方式创建了几个具有不同数据源的FrameworkElements。不幸的是,数据绑定失败了。

我设法将问题提炼到以下程序中:

using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Data;

namespace TestBinding
{
    public class BindingSource : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }
        protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
        {
            if (EqualityComparer<T>.Default.Equals(field, value)) return false;
            field = value;
            OnPropertyChanged(propertyName);
            return true;
        }


        private string _text = "Initial Text";
        public string Text
        {
            get { return _text; }
            set { SetField(ref _text, value); }
        }
    }

    public sealed partial class MainPage : Page
    {
        BindingSource bs = new BindingSource();

        public MainPage()
        {
            this.InitializeComponent();

            TextBlock tb = new TextBlock();
            tb.HorizontalAlignment = HorizontalAlignment.Center;
            tb.VerticalAlignment = VerticalAlignment.Center;
            tb.FontSize = 36;

            Binding bind = new Binding() { Source = bs.Text, Mode=BindingMode.OneWay, UpdateSourceTrigger=UpdateSourceTrigger.PropertyChanged };
            tb.SetBinding(TextBlock.TextProperty, bind);

            Patergrid.Children.Add(tb);
        }

        private void ClickText1(object sender, RoutedEventArgs e)
        {
            bs.Text = "First text button clicked!";
        }

        private void ClickText2(object sender, RoutedEventArgs e)
        {
            bs.Text = "Second text button stroked!";
        }
    }
}

这是xaml:

<Page
    x:Class="TestBinding.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:TestBinding"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid x:Name="Patergrid" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>

        <StackPanel Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Center">
            <Button Content="Text 1" Margin="25" HorizontalAlignment="Center" Click="ClickText1" />
            <Button Content="Text 2" Margin="25" HorizontalAlignment="Center" Click="ClickText2" />
        </StackPanel>
    </Grid>
</Page>

通过在更改属性时单步调试代码,我发现PropertyChanged事件没有订阅者。

为什么没有SetBinding注册PropertyChanged事件?

1 个答案:

答案 0 :(得分:2)

你想要这个:

Binding bind = new Binding()
{
    Source = bs,
    Path = new PropertyPath("Text"),
    Mode = BindingMode.TwoWay,
    UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
};

这里似乎有两个问题:

  1. 您发布的代码尝试使用string属性返回的bs.Text对象,该属性不是可观察的绑定源。绑定系统足够灵活,可以复制一次值,但在此之后,它无法知道对象已经改变了(即使它可以......并且string是一个不可变类型,所以对象赢了'无论如何都要改变。)
  2. 相反,您希望使用BindingSource属性作为路径绑定到Text对象本身作为源。

    1. 此外,将BindingMode.OneWayUpdateSourceTrigger的任何特定设置相结合是没有意义的。当绑定模式是单向的时,源永远不会更新,因此触发器的位置无关紧要。
    2. 使用BindingMode.TwoWay将允许将TextBlock.Text属性中的更改复制回源。

      或者,只是不要打扰设置UpdateSourceTriggerTextBlock无论如何都不是用户可编辑的,所以也许你真的打算让绑定成为单向的,只是将UpdateSourceTrigger的无关初始化从其他东西中删除。从你的问题中很难知道哪种方法适合你的需求。

相关问题