当itemssource更改时,防止WPF组合框清除选择

时间:2013-04-07 19:17:43

标签: wpf xaml binding combobox

我有一个firstname的文本框,一个lastname的文本框和一个displayname的组合框。 displayname是可编辑的,以便用户可以输入他们想要的任何内容。但是,组合框应显示选项列表。

当任一文本框更改时,组合框项目源都会更新。但是,如果用户之前选择一个值,则text属性将被清空。但是,如果用户在值中包含键入,则文本属性仍然存在。如何防止文本值消隐?

这是我的代码:

<Window x:Class="MainWindow"
        x:Name="MainApp"
        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 DataContext="{Binding ElementName=MainApp}">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="auto" />
            <RowDefinition Height="auto" />
            <RowDefinition Height="auto" />
        </Grid.RowDefinitions>
        <TextBox Grid.Row="0"
                 Text="{Binding FirstName}" />
        <TextBox Grid.Row="1"
                 Text="{Binding LastName}" />
        <ComboBox x:Name="MyCb" Grid.Column="1"
                  Grid.Row="2" 
                  Text="{Binding TheName}"
                  ItemsSource="{Binding NameOptions}"
                  IsEditable="True" />
    </Grid>
</Window>

Imports System.ComponentModel

Class MainWindow
    Implements INotifyPropertyChanged

    Public ReadOnly Property NameOptions As List(Of String)
        Get
            Dim result As New List(Of String)
            result.Add(String.Format("{0} {1}", FirstName, LastName))
            result.Add(String.Format("{1}, {0}", FirstName, LastName))
            result.Add(String.Format("{1}, {0} MI", FirstName, LastName))
            Return result
        End Get
    End Property

    Public Property TheName As String

    Private _firstName As String
    Public Property FirstName As String
        Get
            Return _firstName
        End Get
        Set(value As String)
            _firstName = value
            RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("FirstName"))
            RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("NameOptions"))
        End Set
    End Property

    Private _lastname As String
    Public Property LastName As String
        Get
            Return _lastname
        End Get
        Set(value As String)
            _lastname = value
            RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("LastName"))
            RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("NameOptions"))
        End Set
    End Property

    Public Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) Implements INotifyPropertyChanged.PropertyChanged
End Class

2 个答案:

答案 0 :(得分:0)

在更新NameOptions之前将MyCb.SelectedItem设置为null。 SelectedItem取代了Text,当ItemsSource更新时,它还会尝试更新所谓的连接到SelectedItem的Text。

public partial class MainWindow : Window, INotifyPropertyChanged
{
    public List<String> NameOptions 
    {
        get 
        {
            MyCb.SelectedItem = null;   // <--- THIS is the solution. just try it!
            List<String> result = new List<String>();    
            result.Add(String.Format("{0} {1}", FirstName, LastName));
            result.Add(String.Format("{1}, {0}", FirstName, LastName));
            result.Add(String.Format("{1}, {0} MI", FirstName, LastName));
            return result;
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public MainWindow()
    {
        InitializeComponent();            
    }

    private String _theName;
    public String TheName
    {
        get { return _theName; }
        set
        {
            _theName = value;
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs("TheName"));
            }
        }
    }

    private String _firstName;
    public String FirstName
    {
        get { return _firstName; }
        set { 
            _firstName = value; 
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs("NameOptions"));
                handler(this, new PropertyChangedEventArgs("FirstName"));
            }
        }
    }

    private String _lastName;
    public String LastName
    {
        get { return _lastName; }
        set { 
            _lastName = value; 
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs("NameOptions"));
                handler(this, new PropertyChangedEventArgs("LastName"));
            }
        }
    }
}

答案 1 :(得分:0)

请在此处查看我的回答: How to disable ItemsSource synchronization with Text property of ComboBox

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;
        }
    }
}