2

私のXamlにはこれがあります、

<ComboBox x:Name="masterCB" HorizontalAlignment="Left" Margin="5,127,0,0" VerticalAlignment="Top" Width="106" Height="22" Background="White" ItemsSource="{Binding Masters}" FontSize="11" SelectedIndex="{Binding Action}"/>
        <Label Content="Select Action:" HorizontalAlignment="Left" VerticalAlignment="Top" Height="26" Width="116" Margin="0,151,0,0" Background="{x:Null}" FontWeight="Bold"/>

<ListBox x:Name="actionBox" HorizontalAlignment="Left" Height="250" VerticalAlignment="Top" Width="116" Margin="5,177,0,0" ScrollViewer.HorizontalScrollBarVisibility="Disabled" 
            ItemsSource="{Binding ActionList}" AlternationCount="2" MouseDoubleClick="actionBox_DoubleClick">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Grid Background="{x:Null}">
                        <TextBlock Text="{Binding}" TextTrimming="WordEllipsis" TextWrapping="Wrap" Height="40" FontSize="11" />
                    </Grid>
                </DataTemplate>
            </ListBox.ItemTemplate>
            <ListBox.ItemContainerStyle>
                <Style TargetType="{x:Type ListBoxItem}">
                    <Style.Triggers>
                        <Trigger Property="ItemsControl.AlternationIndex" Value="1">
                            <Setter Property="Background" Value="Silver"/>
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </ListBox.ItemContainerStyle>

私のデータクラスには、これがあります。

private List<String> actionList;
public int Action 
   { 
       get{return this.action;} 
       set
       {
           action = value;
           populateActionList();
       } 
   }
 public List<String> ActionList
   {
       get { return actionList; }
       set { this.actionList = value; }
   private void populateActionList()
   {
       if (this.action == 0)
       {
           actionList = new List<String> { 
       "Chinese",
       "Indian",
       "Malay",
       "Indian",
       };
       if (this.action == 1)
       {
           actionList = new List<String> { 
       "Dog",
       "Cats",
       "Pigs",
       "Horses",
       "Fish",
       "Lion"};
       }
   }

printline を実行すると、actionList が変更されますが、ListBox 項目が actionList に設定されません。UI が更新されない理由とその理由を知りたいですか? DataContext と ObservableCollections に変更する必要があることをどこかで読みましたが、それを試してみましたが、まだ更新されません。誰かが理由を知っていますか?

4

4 に答える 4

3

コードを次のように変更すると、期待どおりの結果が得られます

private ObservableCollection<String> _actionList; 

public ObservableCollection<String> ActionList {
  get { 
    if (_actionList == null) {
      _actionList = new ObservableCollection<String>();
    }

    return actionList; 
  }
}

private void populateActionList(){
  if (this.action == 0) {
    ActionList.Clear();

    ActionList.Add("Chinese");
    ActionList.Add("Indian");
    ActionList.Add("Malay");
    ActionList.Add("Indian");
  }

  if (this.action == 1){
    ActionList.Clear();

    ActionList.Add("Dog");
    ActionList.Add("Cats");
    ActionList.Add("Pigs");
    ActionList.Add("Horses");
    ActionList.Add("Fish");
    ActionList.Add("Lion");
  }
}
于 2013-03-19T09:36:40.960 に答える
2

あなたの場合、リスト全体を置き換え、単一のアイテムを追加/削除するのではないため、必要に応じてリストを操作することもできます。そのためには、Jehofが書いたように、コレクションで追加/削除/クリア/置換アクションが実行されたときにCollectionChangedイベント(PropertyChangedではなく)を自動的に発生させるObservableCollectionを使用する必要があります。

コードを機能させるには、次の2つの変更を行う必要があります。

  1. ビューモデルにINotifyPropertyChangedを正しく実装します。データバインドするプロパティごとに、セッターでPropertyChangedイベントを発生させる必要があります。以下の私のコードを参照してください。
  2. actionListバインディングを更新する場合は、プライベートフィールドを変更せず、代わりにプロパティActionListを変更してください。フィールドを変更すると、PropertyChangedイベントが発生しないためです。

覚えておくべきことは次のとおりです。UIは、データバインドされているプロパティのPropertyChangedイベントとCollectionChangedイベントをリッスンします。したがって、UIが更新されない場合、これらのイベントは通常発生しません。

ViewModel:

public class ViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    // Masters
    private List<string> _masters = new List<string>() { "Actions 0", "Actions 1" };
    public List<string> Masters { get { return _masters; } set { _masters = value; OnPropertyChanged("Masters"); } }

    // Action
    private int action;
    public int Action { get { return this.action; } set { action = value; PopulateActionList(); OnPropertyChanged("Action"); } }

    // ActionList
    private List<String> actionList;
    public List<String> ActionList { get { return actionList; } set { this.actionList = value; OnPropertyChanged("ActionList"); } }


    private void PopulateActionList()
    {
        if (this.action == 0)
            this.ActionList = new List<String> { "Chinese", "Indian", "Malay", "Indian" };
        else if (this.action == 1)
            this.ActionList = new List<String> { "Dog", "Cats", "Pigs", "Horses", "Fish", "Lion" };
    }
}
于 2013-03-19T10:12:31.960 に答える
2

コードをすべてコピーし、新しい WPF アプリで実行しました。

バインディングの問題を解決するには、次の 2 つの方法があります。

1 つ目: 次のコードを使用して、メイン ウィンドウで Loaded イベントを作成します。

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    DataContext = this;
    populateActionList();
}

これにより、アプリで次のことが得られます。

アプリの写真

2番目:次のようにXAMLでこれをバインドすることもできます:

MainWindow.xaml で:

window タグに次を追加します。

DataContext="{Binding RelativeSource={RelativeSource Self}}"

次に、コンストラクターで、InitializeComponent() を実行する前にデータを設定してください。

public MainWindow()
{
   populateActionList();
   InitializeComponent();
}
于 2013-03-19T09:44:53.713 に答える
1

ActionListする必要がありますObservableCollection<string>

DataContextプロパティを持つオブジェクトにウィンドウを設定する必要がありますActionList

于 2013-03-19T08:59:51.480 に答える