1

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.

maran87
  • 102
  • 1
  • 10
  • Also, you may need to look into a different solution because a IValueConverter can only take one parameter, yours needs two: the collection and the value to look for. – Steve Konves Jun 27 '12 at 14:59

2 Answers2

1

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.

Community
  • 1
  • 1
Lukasz M
  • 5,635
  • 2
  • 22
  • 29
  • Thanks.I wrote a similar converter , but had some problems with binding. I found your controller much simpler and I used it. – maran87 Jun 28 '12 at 09:22
  • Can i make it a two way binding? If so, should i use convertback to acheive that ? – maran87 Jun 28 '12 at 09:37
  • I am now stuck with the convertback because I am using it two way. Is a convertback possible for this converter /? – maran87 Jun 28 '12 at 16:36
  • How would you like it to work? I suppose you would like it to add(/remove) item to(/from) the list. Remember that in case of converting back, you have one value a parameter (boolean value in this case) and should convert it back to two values to be returned as objects bound. If you would like to update the collection dynamically, I would suggest you to handle `Click` event of the `CheckBox` and add appropriate product to the list there. I suppose you should be able to bind ID to the Tag property to determine which product to add/remove in the handler. – Lukasz M Jun 28 '12 at 17:08
0

In this case, you might be better off calculating the IsChecked value in the ViewModel, the object to which you are binding. If you expose a descriptive property (read-only: HasDesiredProduct) from the VM, you can adjust that property when items are added/removed from the collection and have the checkbox reflect the internal logic in a read-only manner.

cunningdave
  • 1,470
  • 10
  • 13