web-dev-qa-db-ja.com

コレクションが変更されたときにWPFコンボボックスが更新されない

私はWPFを初めて使用します。

文字列のコレクションをコンボボックスにバインドしようとしています。

_public ObservableCollection<string> ListString {get; set;}
_

バインディングとデータコンテキストは次のように設定されます

_<Window 
        x:Class="Assignment2.MainWindow"
        xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
        xmlns:validators="clr-namespace:Assignment2"
        xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525"
        DataContext="{Binding RelativeSource={RelativeSource Self}, Path=.}">
    <Grid>
        <ComboBox  Height="23" HorizontalAlignment="Left" Margin="109,103,0,0" Name="StringComboBox" VerticalAlignment="Top" Width="120" SelectionChanged="StringComboBox_SelectionChanged">
            <ComboBox.ItemsSource>
                <Binding Path="ListString" BindsDirectlyToSource="True" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged"></Binding>
            </ComboBox.ItemsSource>
        </ComboBox>
_

コレクションが更新されているため、これが発生していることがわかりました。私が書いたら

_public MainWindow()
        {

            InputString = "";
            ListString = new ObservableCollection<string>();
            ListString.Add("AAA");
            ListString.Add("BBB");
            ListString.Add("CCC");
          InitializeComponent();

        }
_

動作しますが、次のように最初の行でInitializeComponent()を上に移動すると、動作しません。

_  public MainWindow()
            {
               InitializeComponent();
                InputString = "";
                ListString = new ObservableCollection<string>();
                ListString.Add("AAA");
                ListString.Add("BBB");
                ListString.Add("CCC");                
            }
_

私は何をすべきか??

9
Ganesh Satpute

問題を解決しました。 INotifyPropertyChangedを次のように実装しました

public partial class MainWindow : Window, INotifyPropertyChanged

アクセサを次のように変更しました

    private ObservableCollection<string> listString;
    public ObservableCollection<string> ListString 
    {
        get
        {
            return listString;
        }
        set
        {
            listString = value;
            NotifyPropertyChanged("ListString"); // method implemented below
        }
    }

次のイベントとイベントを発生させる方法を追加しました

public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string name)
{
    if (PropertyChanged != null)
    {
        PropertyChanged(this,new PropertyChangedEventArgs(name));
    }
}

そしてそれは動作しますB)

13
Ganesh Satpute

コードをに変更するとどうなりますか

<Window 
    x:Class="Assignment2.MainWindow"
    xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
    xmlns:validators="clr-namespace:Assignment2"
    xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <ComboBox  Height="23" HorizontalAlignment="Left" Margin="109,103,0,0" Name="StringComboBox" VerticalAlignment="Top" Width="120" SelectionChanged="StringComboBox_SelectionChanged"
               ItemsSource="{Binding ListString, Mode=OneWay}"/>

cs。

  public MainWindow()
        {
           InitializeComponent();
            InputString = "";
            ListString = new ObservableCollection<string>();
            ListString.Add("AAA");
            ListString.Add("BBB");
            ListString.Add("CCC"); 

           this.DataContext=this;    
      }           

ところで:mode = twowayでItemsSourceを設定することは私には意味がありません。コンボボックスがビューモデルの「新しいitemssourceを作成」することはありません。

編集:xamlでDataContextを設定しているため、最初のソリューションが機能すると思います。 InitializeComponent();を呼び出すと、DataContext = "{Binding RelativeSource = {RelativeSource Self}、Path =。}"が実行されると想定しています。また、ListStringプロパティは単なる自動プロパティであり、INotifyPropertyChangedを実装していないため、ctorが新しいListStringプロパティを作成したことはmainwindowviewに通知されません。

  public ObservableCollection<string> ListString {get{return _list;}; set{_list=value; OnPropertyChanged("ListString");}}

両方のアプローチで機能するはずですが、MainWindowクラスにINotifyPropertyChangedを実装する必要があります。

0
blindmeis

私には、問題は「更新」ListStringであったようです。それをプロパティ(選択された答え)にすることは、それを回避する1つの方法です。あるいは、インスタンス化をインライン化するか、InitializeComponentの前に配置しても大丈夫だと思います。

頻繁に更新が行われることが予想される場合は、ObservableCollectionをマネージャークラスにカプセル化すると役立つ場合があります。このような設定で自分の問題をトラブルシューティングした後、この質問を見つけました。 INotifyCollectionChangedを実装し、そのようにイベントを転送することで機能しました

/// <summary>
/// Maintains an observable (i.e. good for binding) collection of resources that can be indexed by name or alias
/// </summary>
/// <typeparam name="RT">Resource Type: the type of resource associated with this collection</typeparam>
public class ResourceCollection<RT> : IEnumerable, INotifyCollectionChanged
    where RT : class, IResource, new()
{
    public event NotifyCollectionChangedEventHandler CollectionChanged
    {
        add { Ports.CollectionChanged += value; }
        remove { Ports.CollectionChanged -= value; }
    }

    public IEnumerator GetEnumerator() { return Ports.GetEnumerator(); }

    private ObservableCollection<RT> Ports { get; set; }
    private Dictionary<string, RT> ByAlias { get; set; }
    private Dictionary<string, RT> ByName { get; set; }
}
0
Assimilater

コードビハインドでコンボボックスのアイテムソースを設定するか、リストにデータが入力された後にデータコンテキストを再度設定するか、inotifychangedを使用してプロパティの変更を行うことができます。

public MainWindow()
        {
            InitializeComponent();
            InputString = "";
            ListString = new ObservableCollection<string>();
            ListString.Add("AAA");
            ListString.Add("BBB");
            ListString.Add("CCC");
            StringComboBox.ItemsSource = ListString;

        }
0
Jason