【问题标题】:Two Way Binding in WPFWPF 中的两种方式绑定
【发布时间】:2010-06-22 09:25:24
【问题描述】:

我是(非常)WPF 新手,对此我有疑问。这可能是一个非常愚蠢的问题,所以如果是这样,请原谅。

我正在做一个项目,我将我的文本框等绑定到单例类中的静态属性。我的问题是双向绑定不起作用。当文本框发生变化时,我可以看到属性的值发生变化,但是当属性发生变化时,我看不到文本框文本发生变化。

为了查看发生了什么,我编写了一个小应用程序,其中仅包含相关代码。请在下面找到代码。

在下面的代码中,我在不同的地方更改了文本框中的文本和源属性,并记录了我的观察结果。如果有人能告诉我我做错了什么并指出我正确的方向,我将不胜感激。

我也尝试过 INotifyPropertyChanged,但由于静态属性,它会出现问题。为静态属性实现 INotifyPropertyChanged 时是否有不同的方法。

提前致谢, 阿比。

XAML:

<Page x:Class="TestBindingApp.Page1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Prefs="clr-namespace:TestBindingApp"
  xmlns:cm="clr-namespace:System.ComponentModel;assembly=System"
  xmlns:winForms="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
  xmlns:wfi="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration"
Title="Page1" Loaded="Page_Loaded">
<Page.Resources>
    <Prefs:Class1 x:Key="TClass"></Prefs:Class1>
</Page.Resources>
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition></RowDefinition>
        <RowDefinition></RowDefinition>
    </Grid.RowDefinitions>
    <StackPanel Orientation="Horizontal" Margin="15 5 5 0" Height="20">
        <TextBlock Name="txbBankNumber" Margin="50 0 0 0" Padding="2">Bank Account Number :</TextBlock>
        <TextBox Name="txtBankNumber" Margin="10 0 0 0" Width="100" MaxLength="8" HorizontalAlignment="Left">
            <TextBox.Text>
                <Binding Source="{StaticResource TClass}" Path="AccountNumber" Mode="TwoWay" NotifyOnValidationError="True" UpdateSourceTrigger="PropertyChanged">
                </Binding>
            </TextBox.Text>
        </TextBox>
    </StackPanel>

</Grid>

XAML.CS:

namespace TestBindingApp
{
/// <summary>
/// Interaction logic for Page1.xaml
/// </summary>
public partial class Page1 : Page
{
    public Page1()
    {

        InitializeComponent();

        txtBankNumber.Text = "ABC";
 // I can see the property AccountNumber changing here
        Class1.AccountNumber = "123456";
 // Value in txtBankNumber doesn't change here
    }

    private void Page_Loaded(object sender, RoutedEventArgs e)
    {
        txtBankNumber.Text = "ABCDE";
 // I can see the property AccountNumber changing here

        Class1.AccountNumber = "12345678";
 // Value in txtBankNumber doesn't change here

    }
}

}

Class Class1:

using System.ComponentModel;

namespace TestBindingApp
{
public class Class1
{
    // Singleton instance
    private static Class1 instance;
    private static string _accountNumber;
    public Class1()
    {

    }

    // Singleton instance read-only property
    public static Class1 Instance
    {
        get
        {
            if (instance == null)
            {
                instance = new Class1();
            }
            return instance;
        }
    }

    public static string AccountNumber
    {
        get
        {
            return _accountNumber;
        }
        set
        {
            if (value != _accountNumber)
            {
                _accountNumber = value;
            }
        }
    }
}

}

======================

无法在 cmets 中发布我更新的代码,因此更新我的原始帖子。

下面是我更新的代码,其中包含“if(PropertyChanged != null)”,但它给了我一个错误 - “非静态字段、方法或属性 'TestBindingApp.Class1 需要对象引用.NotifyPropertyChanged(字符串)'”。 .

我刚开始学习WPF,所以如果你能详细解释一下,那将非常有帮助。感谢您的耐心等待。

using System.ComponentModel;

namespace TestBindingApp
{
public class Class1: INotifyPropertyChanged
{
    // Singleton instance
    private static Class1 instance;
    private static string _accountNumber;
    public event PropertyChangedEventHandler PropertyChanged;

    public Class1()
    {

    }

    // Singleton instance read-only property
    public static Class1 Instance
    {
        get
        {
            if (instance == null)
            {
                instance = new Class1();
            }
            return instance;
        }
    }

    public static string AccountNumber
    {
        get
        {
            return _accountNumber;
        }
        set
        {
            if (value != _accountNumber)
            {
                _accountNumber = value;
                NotifyPropertyChanged("AccountNumber");
            }
        }
    }

    private void NotifyPropertyChanged(string property)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(property));
    } 

}

}

==============

更新于英国时间 6 月 23 日上午 9:53

嗨,Arcturus,我已将属性更改为非静态的,但它的行为仍不符合我的预期。我是在期待它做一些它不应该做的事情,还是我做错了什么。 在下面的代码中,我希望文本框显示 12345678(或者可能是 123456)作为帐号,但它仍然显示 123。在调试模式下,我可以看到 PropertyChanged 事件在每个属性更改语句后正确执行,但值文本框不会改变。绑定仅在初始化时生效(InitializeComponent()),还是我在这里遗漏了什么?

页面代码隐藏

namespace TestBindingApp
{
/// <summary>
/// Interaction logic for Page1.xaml
/// </summary>
public partial class Page1 : Page
{
    public Page1()
    {
        Class1.Instance.AccountNumber = "123";
        InitializeComponent();
        Class1.Instance.AccountNumber = "123456";
    }

    private void Page_Loaded(object sender, RoutedEventArgs e)
    {
        Class1.Instance.AccountNumber = "12345678";
    }
}
}

Class1.cs

namespace TestBindingApp
{
public class Class1: INotifyPropertyChanged
{
    // Singleton instance
    private static Class1 instance;
    private static string _accountNumber;
    public event PropertyChangedEventHandler PropertyChanged = delegate { };

    public Class1()
    {

    }

    // Singleton instance read-only property
    public static Class1 Instance
    {
        get
        {
            if (instance == null)
            {
                instance = new Class1();
            }
            return instance;
        }
    }

    public string AccountNumber
    {
        get
        {
            return _accountNumber;
        }
        set
        {
            if (value != _accountNumber)
            {
                _accountNumber = value;
                OnPropertyChanged("AccountNumber");
            }
        }
    }

    private void OnPropertyChanged(string property)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(property));
        }
    } 

}
}

【问题讨论】:

    标签: c# wpf


    【解决方案1】:

    你确实需要 INotifyPropertyChanged 接口:

    using System.ComponentModel;
    
    namespace TestBindingApp
    {
    public class Class1
    {
        // Singleton instance
        private static Class1 instance;
        private string _accountNumber;
        public Class1()
        {
    
        }
    
        // Singleton instance read-only property
        public static Class1 Instance
        {
        get
        {
            if (instance == null)
            {
            instance = new Class1();
            }
            return instance;
        }
        }
    
        public string AccountNumber
        {
        get
        {
            return _accountNumber;
        }
        set
        {
            if (value != _accountNumber)
            {
            _accountNumber = value;
                NotifyPropertyChanged("AccountNumber");
            }
        }
        }
    
            public event PropertyChangedEventHandler PropertyChanged;
    
    
        private void NotifyPropertyChanged(string property)
        {
            if(PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(property));
        }
    }
    

    【讨论】:

    • 我以前尝试过这种方法,但它给了我一个错误 - “非静态字段、方法或属性 'TestBindingApp.Class1.NotifyPropertyChanged(string)' 需要对象引用” .看起来是因为静态类。是否有其他方法可以为静态属性实现 INotifyPropertyChanged?
    • 请注意 NotifyPropertyChanged 中的 if(PropertyChanged != null)。它的存在是有原因的 ;)
    • 抱歉,大角星,我没明白你的意思。无法在 cmets 中发布我更新的代码,因此更新了我的原始帖子。我更新的代码有“if(PropertyChanged != null)”,但它给了我一个错误 - “非静态字段、方法或属性'TestBindingApp.Class1.NotifyPropertyChanged(string)'需要对象引用” . .我刚开始学习WPF,所以如果你能详细解释一下,那将非常有帮助。谢谢你的耐心。谢谢,阿比。
    • 另外,我更喜欢将 PropertyChanged 设置为一个空委托,然后我就不必担心空检查:public event PropertyChangedEventHandler PropertyChanged = delegate { };
    • 如果我给出“txtBankNumber.GetBindingExpression(TextBox.TextProperty).UpdateTarget();”更改 AccountNumber 属性的值后,文本框属性更改正常。这意味着绑定设置正确,但由于我需要做一些事情,NotifyPropertyChanged 事件无法正常工作。还有其他想法吗?
    【解决方案2】:

    您从静态成员调用 NotifyPropertyChanged,但 NotifyPropertyChanged 本身不是静态的。

    两种解决方法:要么让 AccountNumber 不是静态的,要么为您调用 NotifyPropertyChanged 提供一个实例(例如“Instance.NotifyPropertyChanged(...)”)

    【讨论】:

    • 我无法将属性更改为非静态,因为这不会达到目的。我将 NotifyPropertyChanged("AccountNumber") 更改为 Instance.NotifyPropertyChanged("AccountNumber")。该应用程序构建良好,但仍然无法正常工作。当它进入 NotifyPropertyChanged 方法时,PropertyChanged 为 null 并且它不会更改文本框的值。有什么想法吗?
    • 如果我给出“txtBankNumber.GetBindingExpression(TextBox.TextProperty).UpdateTarget();”更改 AccountNumber 属性的值后,文本框属性更改正常。这意味着绑定设置正确,但由于我需要做一些事情,NotifyPropertyChanged 事件无法正常工作。还有其他想法吗?
    猜你喜欢
    • 2017-01-03
    • 2021-03-01
    • 2016-10-24
    • 2012-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-09
    • 1970-01-01
    相关资源
    最近更新 更多