簡體   English   中英

控制不立即使用INotifyPropertyChanged更新綁定屬性

[英]Control not immediately updating bound property with INotifyPropertyChanged

我有控件在焦點丟失之前不更新綁定對象的相應屬性。 關於正在聲明的DataSourceUpdateMode.OnPropertyChange引用的答案也有類似的問題,我這樣做,但行為仍然存在。 這是一個示例實現。 我會盡量徹底,但要簡潔。 MyConfig類是通過我調用Configuration的Singleton類中的屬性訪問的。

[Serializable]
public class MyConfig : INotifyPropertyChanged
{
    public enum MyEnum
    {
        Foo,
        Bar
    }

    public MyConfig()
    {
        MyProperty = MyEnum.Foo;
    }

    private MyEnum _MyProperty;
    public MyEnum MyProperty
    {
        get { return _MyProperty; }
        set { if (value != _MyProperty) { _MyProperty = value; OnPropertyChanged("MyProperty"); } }
    }

    [field: NonSerialized]
    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string propertyName)
    {
        if (string.IsNullOrEmpty(propertyName))
            throw new ArgumentNullException(propertyName);
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

public partial class ConfigForm : Form
{
    public ConfigForm()
    {
        InitializeComponent();
        MyComboBox.Items.AddRange(Enum.GetNames(typeof(MyConfig.MyEnum)));
    }

    private void ConfigForm_Load(object sender, EventArgs e)
    {
        MyComboBox.DataSource = Enum.GetValues(typeof(MyConfig.MyEnum));
        MyComboBox.DataBindings.Add("SelectedItem", Configuration.Instance.MyConfig, "MyProperty", false, DataSourceUpdateMode.OnPropertyChanged);
    }
}

鑒於以下簡要實施,我不確定我可以忽視什么以確保立即改變財產。 我可以改變,在這種情況下,從Foo到ComboBox中的Bar ,但除非我從ComboBox中刪除焦點,否則沒有任何變化。 有沒有人有任何想法?

關於OnPropertyChanged ,WinForms ComboBoxOnPropertyChanged 這里是一些舊項目的代碼,我曾經以OnPropertyChanged的方式運行我對SelectedItem屬性的期望。 這適用於我的具體實例,但我通常很難讓這種情況有時起作用。 祝好運!

/// <summary>
/// A modification of the standard <see cref="ComboBox"/> in which a data binding
/// on the SelectedItem property with the update mode set to DataSourceUpdateMode.OnPropertyChanged
/// actually updates when a selection is made in the combobox.
/// </summary>
public class BindableComboBox : ComboBox
{
    /// <summary>
    /// Raises the <see cref="E:System.Windows.Forms.ComboBox.SelectionChangeCommitted"/> event.
    /// </summary>
    /// <param name="e">An <see cref="T:System.EventArgs"/> that contains the event data.</param>
    protected override void OnSelectionChangeCommitted(EventArgs e)
    {
        base.OnSelectionChangeCommitted(e);

        var bindings = this.DataBindings
            .Cast<Binding>()
            .Where(x => 
                x.PropertyName == "SelectedItem" && 
                x.DataSourceUpdateMode == DataSourceUpdateMode.OnPropertyChanged);
        foreach (var binding in bindings)
        {
            // Force the binding to update from the new SelectedItem
            binding.WriteValue();

            // Force the Textbox to update from the binding
            binding.ReadValue();
        }
    }
}

@Nicholas Piasecki因為引導我找到我的解決方案而值得稱贊,除非你根據他的回答找不到解決方案,否則請投票給他答案。


在我的情況下,我必須為此修復程序進行三項主要更改。

  • 我試圖訪問綁定到ComboBox的SelectedValue屬性的對象的屬性。 因此,我必須在Linq where子句中包含“SelectedValue”屬性名稱。

  • 如果您通過Visual Studio中的表單設計器設置數據綁定,並只是設置SelectedValue或SelectedItem綁定的內容,則默認數據源更新模式為“OnValidation”。 如果您轉到ComboBox上的數據綁定的“(高級)”設置,則可以看到此信息。 因此,您必須包含該數據源更新模式,如果您正在使用它。

  • 在我的情況下,我還必須循環綁定並執行Write / ReadValue調用之后引發OnSelectionChangeCommitted事件。 由於我在表單上訂閱了ComboBox的SelectionChangeCommitted事件,因此在循環綁定並強制它們更新之前調用base.OnSelectionChangeCommitted導致綁定對象的屬性仍未設置。

所以,這是我的@Nicholas Piasecki的答案(也轉換為VB.NET):

''' <summary>
''' Raises the <see cref="E:System.Windows.Forms.ComboBox.SelectionChangeCommitted"/> event _after_ forcing any data bindings to be updated.
''' </summary>
''' <param name="e">An <see cref="T:System.EventArgs"/> that contains the event data.</param>
Protected Overrides Sub OnSelectionChangeCommitted(e As EventArgs)
    Dim bindings As List(Of Binding) = ( _
        From x In Me.DataBindings.Cast(Of Binding)()
        Where (x.PropertyName = "SelectedItem" OrElse x.PropertyName = "SelectedValue" OrElse x.PropertyName = "SelectedIndex") AndAlso
              (x.DataSourceUpdateMode = DataSourceUpdateMode.OnPropertyChanged OrElse x.DataSourceUpdateMode = DataSourceUpdateMode.OnValidation)
    ).ToList()

    For Each b As Binding In bindings
        ' Force the binding to update from the new SelectedItem
        b.WriteValue()
        ' Force the Textbox to update from the binding
        b.ReadValue()
    Next

    MyBase.OnSelectionChangeCommitted(e)
End Sub

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM