WPF双向数据绑定到Textbox.Text仅在一个方向上起作用

时间:2019-09-20 19:32:07

标签: c# wpf data-binding

我的问题不是关于序列化,我正在使序列化部分工作正常,但在上下文中,我试图序列化用户以WPF形式设置的某些属性,因此需要双向绑定(只能朝一个方向工作:目标到源的更新)。

假设我已经定义了一个应用程序属性,该属性是我要序列化的属性的容器:

public SerializableApplicationProperties ThisAppsSerializableProperties { get; set; }

SerializableApplicationProperties类如下:

[Serializable]
public class SerializableApplicationProperties
{

    public SerializableApplicationProperties()
    {
        UserSelectedPreFillFilePath = new ObservableString();
    }

    public SerializableApplicationProperties(string defaultFilePath)
    {
        UserSelectedPreFillFilePath = new ObservableString(defaultFilePath);
    }

    public ObservableString UserSelectedPreFillFilePath { get; set; }

}

到目前为止,我已经定义了一个属性,因此我需要在代码中建立两种方式绑定(是的,在代码中)。请不要建议如何在XAML标记中执行此操作,除非您还通过代码说明了如何完全执行此操作。

该属性为“ UserSelectedPreFillFilePath”,您可以看到其类型为“ ObservableString”。

ObservableString类看起来像这样:

 [Serializable]
    public class ObservableString : INotifyPropertyChanged
    {

        private string _stringValue;
        public string StringValue
        {
            get { return _stringValue; }
            set
            {
                _stringValue = value;
                OnPropertyChanged("StringValue");
            }
        }

        public ObservableString() { }

        public ObservableString(string value)
        {
            this._stringValue = value;
        }

        protected void OnPropertyChanged(string name)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(name));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

    }

一个非常简单的类,具有“ StringValue”属性并实现INotifyChange。

然后,我尝试在此“ UserSelectedPreFillFileLocation”和主窗口上的文本框之间建立双向绑定。

我想要双向绑定,以便在关闭应用程序之前可以序列化UserSelectedPreFillFileLocation属性(该属性应根据用户在窗口文本框中的内容自动更新)。

然后,当应用程序从文件加载(反序列化)该文本框时,将通过绑定使用UserSelectedPreFillFileLocation值自动填充该文本框。

第二件事,我的转换器类定义:

[ValueConversion(typeof(ObservableString), typeof(string))]
class ObservableStringToStringConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        ObservableString myVar = (ObservableString)value;
        return myVar.StringValue;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        string myVar = (string)value;
        return new ObservableString(myVar);
    }
}

最后是绑定的定义。绑定对源到目标有效,但反之则不行。即当用户更新文本框时,UserSelectedPreFillFileLocation会更新,但反之则不会。

        Binding UserSelectedPreFillFilePathBinding = new Binding();
        UserSelectedPreFillFilePathBinding.Path = new PropertyPath(nameof(ThisAppsSerializableProperties.UserSelectedPreFillFilePath));
        UserSelectedPreFillFilePathBinding.Source = ThisAppsSerializableProperties;          
        UserSelectedPreFillFilePathBinding.Converter = new ObservableStringToStringConverter();
        UserSelectedPreFillFilePathBinding.Mode = BindingMode.TwoWay;
        UserSelectedPreFillFilePathBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
        ThisAppInstanceMainWindow.TxtbxPrefillFileLocation.SetBinding(TextBox.TextProperty, UserSelectedPreFillFilePathBinding);

1 个答案:

答案 0 :(得分:-1)

我发现我做错了。

我确实定义了一个ObservableString,引发属性更改事件的observable属性是该类中的StringValue。

因此,在这种情况下,我什至不需要转换器,因为我应该为绑定定义的源属性是StringValue,而源对象应该是UserSelectedPreFillFilePath。

已更正的代码现在可以很好地用于双向绑定:

        Binding UserSelectedPreFillFilePathBinding = new Binding();
        UserSelectedPreFillFilePathBinding.Path = new PropertyPath(nameof(ThisAppsSerializableProperties.UserSelectedPreFillFilePath.StringValue));
        UserSelectedPreFillFilePathBinding.Source = ThisAppsSerializableProperties.UserSelectedPreFillFilePath;
        UserSelectedPreFillFilePathBinding.Mode = BindingMode.TwoWay;
        UserSelectedPreFillFilePathBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
        ThisAppInstanceMainWindow.TxtbxPrefillFileLocation.SetBinding(TextBox.TextProperty, UserSelectedPreFillFilePathBinding);