簡體   English   中英

如何使用ComboBox的Text屬性禁用ItemsSource同步

[英]How to disable ItemsSource synchronization with Text property of ComboBox

我使用ComboBox綁定到視圖模型的字符串屬性。 我選擇ComboBox而不是TextBox,因為我希望有一個選項可以從列表中選擇(作為建議),但如果ItemsSource更改,我不想更改所選文本。

我嘗試將IsSynchronizedWithCurrentItem屬性設置為false,但是當建議列表更改時(在所選文本的位置),文本將更改為空。 似乎ComboBox記得輸入的文本也在列表中,當此項消失時,Text屬性也被清除。

所以我的問題是:這是一個錯誤,還是我做錯了什么? 如果它是一個bug,你能建議一些解決方法嗎?

我創建了一個示例項目,它預先生成了這個:

在XAML中:

<Window x:Class="TestProject1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <ComboBox IsSynchronizedWithCurrentItem="False" ItemsSource="{Binding Items}"
                  IsEditable="True" Text="{Binding SelectedText, UpdateSourceTrigger=PropertyChanged}"
                  HorizontalAlignment="Left" Margin="10,39,0,0" VerticalAlignment="Top" Width="120"/>
        <Button Click="Button_Click" Content="Update list" 
                HorizontalAlignment="Left" Margin="10,82,0,0" VerticalAlignment="Top" Width="75"/>
    </Grid>
</Window>

代碼背后:

public partial class MainWindow : Window, INotifyPropertyChanged
    {
        public MainWindow() {
            InitializeComponent();

            this.DataContext = this;
            Items = new List<string>() { "0", "1", "2" };
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void RaisePropertyChanged(string propertyName) {
            if (PropertyChanged != null) {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        private List<string> _items;
        public List<string> Items {// I use IEnumerable<string> with LINQ, but the effect is the same
            get { return _items; }
            set {
                if (_items != value) {
                    _items = value;
                    RaisePropertyChanged("Items");
                }
            }
        }

        private string _selectedText;
        public string SelectedText {
            get { return _selectedText; }
            set {
                if (_selectedText != value) {
                    _selectedText = value;
                    RaisePropertyChanged("SelectedText");
                }
            }
        }

        private void Button_Click(object sender, RoutedEventArgs e) {
            var changed = Items.ToList();//clone
            int index = changed.IndexOf(SelectedText);
            if (index >= 0) {
                changed[index] += "a";//just change the currently selected value
            }
            Items = changed;//update with new list
        }

    }

這是我對該問題的修復:

public class ComboBox : System.Windows.Controls.ComboBox
{
    private bool ignore = false;
    protected override void OnSelectionChanged(SelectionChangedEventArgs e)
    {
        if (!ignore)
        {
            base.OnSelectionChanged(e);
        }
    }

    protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e)
    {
        ignore = true;
        try
        {
            base.OnItemsChanged(e);
        }
        finally
        {
            ignore = false;
        }
    }
}

ItemsSource更改后,在所選文本上引發更改的屬性以刷新UI。

因此,在Items集合setter中,進行更改:

RaisePropertyChanged("Items");
RaisePropertyChanged("SelectedText");

編輯:在您的示例中,您不僅僅是更改ItemSource,而是更改當前所選項目的文本,但對舊文本具有文本綁定。 你期待看到/發生什么? 您是否希望所選項目保持不變,即使其文本發生變化?

像這樣修改Button_Click (注釋行是新的):

private void Button_Click(object sender, RoutedEventArgs e)
{
    string tempCopy = SelectedText; // Create a copy of the current value

    var changed = Items.ToList();
    int index = changed.IndexOf(SelectedText);
    if (index >= 0)
    {
        changed[index] += "a";
    }
    Items = changed;

    SelectedText = tempCopy; // Replace the selected text with the copy we made
}

所有這一切都是在Items更改之前復制SelectedText ,然后在更改完成后替換它。

  1. 復制SelectedText
  2. 修改項目來源
  3. SelectedText替換為副本

暫無
暫無

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

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