Search code examples
wpfbindingcheckboxdatatemplate

Collection to boolean converter


In my wpf app, I have a datagrid as follows

                            <Custom:DataGrid x:Name="dg_nba" IsEnabled="{Binding Iseditmode}" SelectionMode="Single" ItemsSource="{Binding Products}" Style="{DynamicResource myDataGridStyle}" IsReadOnly="True" AutoGenerateColumns="False" CanUserAddRows="False" ColumnWidth="*">
                        <Custom:DataGrid.Columns>
                            <Custom:DataGridTextColumn x:Name="dgt_nba_id" Header="Id" Binding="{Binding ID}" MaxWidth="40"/>
                            <Custom:DataGridTextColumn x:Name="dgt_nba_name" Binding="{Binding Name}" Header="Name"/>
                            <Custom:DataGridTemplateColumn x:Name="dgtc_nba_incl" Header="Include" MaxWidth="50">
                                <Custom:DataGridTemplateColumn.CellTemplate >
                                    <DataTemplate>
                                            <CheckBox HorizontalAlignment="Center" Style="{DynamicResource myCheckBoxStyle}"/>
                                    </DataTemplate>
                                </Custom:DataGridTemplateColumn.CellTemplate>
                            </Custom:DataGridTemplateColumn>
                        </Custom:DataGrid.Columns>
                    </Custom:DataGrid>

I have binded the datagrid id , name column with the Default collection of Products. I have another collection of product list which has only the products included, Now i need to check the checkbox if the list contains the product.

Can someone help me with the Collection to boolean converter. I tried my best but wasnt able to get it right.

Thanks in advance.


Solution

  • If you want to use value converter I would suggest you to try IMultiValueConverter. You can try to pass the other collection as a value and the ID you are looking for as two different values passed to the converter. In order to make it work, you should:

    • make you code-behind variable accessible in XAML. You can find more information about some of the methods to do it here: Access codebehind variable in XAML
    • implement IMultiValueConverter. It can depend on some details of your application (like type of the collection you ae using), but it may look more or less like this:

      class ICollectionToBoolConverter : IMultiValueConverter
      {
          public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
          {
              try
              {
                  //verify if appropriate number of values is bound
                  if (values != null && values.Length == 2)
                  {
                      List<Product> productsList = (values[0] as List<Product>);
      
                      //if converter is used with appropriate collection type
                      if (productsList != null)
                      {
                          //if there is object ID specified to be found in the collection
                          if (values[1] != null)
                          {
                              int objectToFindId = (int)values[1];
      
                              //return information if the collection contains an item with ID specified in parameter
                              return productsList.Any(p => p.ID == objectToFindId);
                          }
                      }
                  }
      
                  //return false if object is not found or converter is used inappropriately
                  return false;
              }
              catch
              {
                  return false;
              }
          }
      
          public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
          {
              throw new NotImplementedException();
          }
      }
      
    • put your newly created converter in Resources of Window (or UserControl) where the DataGrid resides

      <c:ICollectionToBoolConverter x:Key="collectionToBoolConverter" />
      
    • bind the CheckBox using the converter, it can depend on specific way you use to expose the other collection (as mentioned in the first step of this answer). However, it may look similar to this:

      ...
      <Custom:DataGridTemplateColumn.CellTemplate>
          <DataTemplate>
              <CheckBox HorizontalAlignment="Center" Style="{DynamicResource myCheckBoxStyle}">
                  <CheckBox.IsChecked>
                      <MultiBinding Converter="{StaticResource collectionToBoolConverter}">
                          <Binding  ElementName="layoutRoot" Path="Parent.MyCollectionName" />
                          <Binding Path="ID" />
                      </MultiBinding>
                  </CheckBox.IsChecked>
              </CheckBox>
          </DataTemplate>
      </Custom:DataGridTemplateColumn.CellTemplate>
      ...
      

    I haven't tested this, so if you have any issues with any of those tasks, let me know and I can try to help you.