将ComboboxItem作为复选框绑定到列表中的存在吗?

时间:2018-11-09 19:22:12

标签: c# wpf checkbox data-binding

我是wpf的新手,除了阅读“释放WPF”之外,我尝试编写一些小程序,这为我提供了前进的方向。 所以这是我的问题:我想用一个小的图书馆程序在家管理我的书。每本书都存储在Book类实例中。因此,此Book类包含该书的所有信息,以及其中的关键词,这是'Keywords'属性中的ObservableCollection:

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

(_ keywords是一个字符串)。

我想要的是显示一个文本框和一个组合框,以显示相关信息:文本框显示所选书籍的所有关键字,组合框显示复选框列表,并由所有列表填充库中所有书籍中的关键字,列出一次(重复删除),然后选中每个复选框,如果所选书籍的列表框中都存在该关键字。 我将尝试以不同的方式解释它:每本书都包含所有关键字的列表。组合框包含(所有书籍中的)所有现有关键字,并且选中了与所选书籍相关的那些:它允许我通过两种方式添加/编辑/删除关键字:通过文本框,或者通过选中/取消选中复选框。

回到我的问题:如何使用最大的数据绑定对此进行编码? 对于文本框,我认为没有问题:我将在“书”中创建一个属性,例如“ KeywordsForTextbox”,只有一个吸气剂会返回与适当的分隔符合并的关键字集合项。然后,使用指向selectedBook的dataContext,将文本框的text属性绑定到keywordForTextbox。 我宁愿暂时不考虑文本框版本。

但是对于组合框,有两件事需要绑定: 1 /所有关键字的列表。我可以在我的BookManagement类(它管理Book类)中添加一个属性,该属性的getter将返回所有关键字的列表(通过链接)。 2 /每个ComboboxItem都将在XAML中进行编辑,但是如果给定的关键字(使用Book实例的Keyword属性的复选框的ItemSource属性获取)包含在selectedItem中,则如何实现将其设置为选中/未选中的行为关键字?

不久之后:如何将CheckBoxItem的checked属性绑定到listView的selectedItem.Keywords(字符串列表)中此字符串的存在?

我为我的问题的混乱之处表示歉意!

谢谢。

编辑

好吧,我设法编写了所有东西,它可以构建并运行,但是有一个问题。实际上,在组合框中,itemsSource的编写方式如下:

ItemsSource="{Binding Source={StaticResource AllBooks}}"

而AllBooks是资源:

<ObjectDataProvider
  x:Key="AllBooks"
  MethodName="listOfAllKeywords"
  ObjectType="{x:Type mangmt:BookManagement}" />

这是方法:

public static ObservableCollection<string> listOfAllKeywords()
        {
            if (App.Books != null)
            {

                IEnumerable<string> kws = App.Books.SelectMany(book => book.Keywords).Distinct();
                return new ObservableCollection<string>(kws);

            }
            else return new ObservableCollection<string>();


        }

运行程序时,窗口会正常显示,但是如果我单击一本书以显示它,并且单击组合框,则在第二次单击时会出现异常: System.InvalidCastException:'类型'MS.Internal.NamedObject'和类型'System.String'的无效效果。 这说演员是不可能的。 我在调试中看到,在多重绑定中,seconf参数为null(无论如何,它似乎不太相关,因为异常是由第一个参数引起的,但很烦人)。

我记得你我的多重绑定:

<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,Mode=TwoWay}">

                        <ComboBox.ItemTemplate>
                            <DataTemplate>
                                <StackPanel Orientation="Horizontal">
                                    <CheckBox Width="200">
                                        <MultiBinding Converter="{StaticResource TextInListTrueFalseConverter}" >
                                            <Binding Path="KeywordsForTextbox"></Binding>
                                            <Binding RelativeSource="{RelativeSource Self}" Path="Content"></Binding>
                                            </MultiBinding>
                                    </CheckBox>
                                </StackPanel>
                            </DataTemplate>
                        </ComboBox.ItemTemplate>
                    </ComboBox>

这是KeywordsForTextBox:

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

        }

(在Book类中) (multibinding)中的第一个绑定是错误的吗?

谢谢。

编辑2 我创建了一个新帖子,因为该帖子太乱了(我的问题中的文字太多),并且可能的原因区域受到很大限制,因为我看到这是一个dependencyProperty问题。这是链接:here in stack overflow

1 个答案:

答案 0 :(得分:1)

基于我在评论中的建议IMultiValueConverter(对不起,在VB中):

Public Class TextInListTrueFalseConverter
    Implements IMultiValueConverter

    Public Function Convert(values() As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object Implements IMultiValueConverter.Convert
        Dim Checked As Boolean = False
        If Not values Is Nothing Then
            If values.Count = 2 Then
                Dim ListString As String = values(0)
                Dim WordToFind As String = values(1)
                If Not ListString Is Nothing Then
                    Dim KeywordList As List(Of String) = ListString.Split(";").ToList 'Assuming you seperator is a ;
                    If KeywordList.Contains(WordToFind) Then Checked = True
                End If
            End If
        End If
        Return Checked
    End Function

    Public Function ConvertBack(value As Object, targetTypes() As Type, parameter As Object, culture As CultureInfo) As Object() Implements IMultiValueConverter.ConvertBack
        Throw New NotImplementedException()
    End Function
End Class

XAML:

<CheckBox >
    <CheckBox.IsChecked>
        <MultiBinding Converter="{StaticResource TextInListTrueFalseConverter}">
             <Binding Path="KeywordsForTextbox" />
             <Binding RelativeSource="{RelativeSource Self}" Path="Content" />
        </MultiBinding>
    </CheckBox.IsChecked>
</CheckBox>

(使用Combo的DataContext绑定到Book类,并使用ItemsSource加载关键字)

最后,将<Local:TextInListTrueFalseConverter x:Key="TextInListTrueFalseConverter" />添加为资源,并添加“ Local”命名空间(如果尚不存在)。 xmlns:Local="clr-namespace:APPNAME"

未经测试,但认为它应该可以工作,或者至少可以给您带来继续的机会。

编辑

我的坏。我想到ComboBoxItems将从ComboBox继承DataContext,但它们当然不继承-它们显然绑定到ItemsSource。尝试以下更改,我已将第一个绑定更新为Books ListBox。我还在适当的地方添加了<CheckBox.IsChecked>,还向CheckBox添加了Content="{Binding}"

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

您还可能希望向IMultiValueConverter添加一些验证,以确保传递的值未设置为避免异常:VB中的If Not values(0) Is DependencyProperty.UnsetValue And Not values(1) Is DependencyProperty.UnsetValue Then