使用数据绑定时不会刷新listview

时间:2018-11-12 15:16:21

标签: c# wpf data-binding

我有一个模型类Book,其中包含一个关键词属性:

public class Book : INotifyPropertyChanged
{
    private ObservableCollection<string> _keywords;
    ...
    public ObservableCollection<string> Keywords
    {
        get => _keywords;
        set
        {
            _keywords = value;
            OnPropertyChanged("Keywords");
        }
    }
}

在我的主页中,我有2个组成部分:一个列表视图和一个组合框,其每个条目都是一个复选框:

<ComboBox
    x:Name="cbb_Keywords"
    Grid.Column="2"
    Width="300"
    Margin="5,0,0,0"
    HorizontalAlignment="Left"
    ItemsSource="{Binding Source={StaticResource AllBooks}}"
    DataContext="{Binding ElementName=listBoxBooks,Path=SelectedItem,UpdateSourceTrigger=PropertyChanged}">


    <ComboBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <CheckBox Width="200" Content="{Binding}" Click="ButtonBase_OnClick">
                    <CheckBox.IsChecked>
                        <MultiBinding Converter="{StaticResource TextInListTrueFalseConverter}" Mode="OneWay">
                            <Binding ElementName="listBoxBooks" Path="SelectedItem.KeywordsForTextbox" Mode="OneWay"></Binding>
                            <Binding RelativeSource="{RelativeSource Self}" Path="Content"></Binding>
                        </MultiBinding>
                    </CheckBox.IsChecked>
                </CheckBox>
            </StackPanel>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

checkBox.IsChecked多重绑定是单向的,当我单击一个复选框时,它将调用此方法:

private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
    CheckBox cb = (CheckBox)sender;
    var content = (string)cb.Content;
    var keywords = ((Book)listBoxBooks.SelectedItem).Keywords;
    bool clicked = cb.IsChecked.Value;
    if (clicked)
        keywords.Add(content);
    else
        keywords.Remove(content);  
}

它或多或少有效,但有两个警告:

  • 有时,我刚刚单击的复选框会显示在组合框的复选框中,这不是预期的,而且很烦人

  • 除了组合框,我还有一个其他组件,一个文本框,其中包含列表视图的selectedItem的关键字列表:

here

但是当我单击一个复选框以使其混乱时,包含该列表的列表框不会刷新...

所以我在Book中做了一些我的关键词属性:

public ObservableCollection<string> Keywords
{
    get => _keywords;
    set
    {
        _keywords = value;
        OnPropertyChanged("Keywords");
        OnPropertyChanged("KeywordsForTextbox");
    }
}

,KeywordsForTextbox属性如下:

public string KeywordsForTextbox
{
    get { return string.Join(",", _keywords); }    
}

最后,要完整,这是我的MainWindow中的textBox组件:

<TextBox x:Name="txb_Keywords"
         Grid.Column="1"
         Width="500"
         Text="{Binding ElementName=listBoxBooks,Path=SelectedItem.KeywordsForTextbox,Mode=OneWay,UpdateSourceTrigger=PropertyChanged}" />

为什么该复选框出现在组合框的文本框中?为什么不刷新另一个文本框?

谢谢。

1 个答案:

答案 0 :(得分:1)

问题在于修改关键字集合时,实际的关键字属性不会更改。它仍然是相同的集合对象。仅对象的属性(项)会更改。

在Book类中,您可以使用方法进行添加和删除,然后从此处通知属性更改。

public void AddKeyword(string name)
{
    Keywords.Add(name);
    OnPropertyChanged("Keywords");
}

public void RemoveKeyword(string name)
{
    Keywords.Remove(name);
    OnPropertyChanged("Keywords");
}

然后像这样更改您的活动。

private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
    CheckBox cb = (CheckBox)sender;
    var content = (string)cb.Content;
    var book = ((Book)listBoxBooks.SelectedItem);
    bool clicked = cb.IsChecked.Value;
    if (clicked)
        book.AddKeyword(content);
    else
        book.RemoveKeyword(content);
}