1

I have bound a flagged enum to a bunch of checkboxes by using a value converter that works as described in the solution to this question. This works fine when I'm working with a flag that hasn't been set to anything.

However, in the non-trivial use case that the flag is actually set to some data, on load the checkboxes are bound correctly to the enum field. However, when I check/uncheck the box, it seems this binding has been lost.

For example, my enum and value converters are as follows:

[Flags]
enum Fruits : int { Apple = 1, Orange = 2, Peach = 4, None = 0 };

public Converter : IValueConverter
{
    private Fruits target;

    public Converter() { }

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        Fruits mask = (Fruits)parameter;
        this.target = (Fruits)value;
        return ((mask & this.target) != 0);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        this.target ^= (Fruits)parameter;
        return this.target;
    }
}

My XAML (in a datagrid) is as follows:

<toolkit:DataGrid.Columns>
    <toolkit:DataGridTemplateColumn Header="Fruits">
        <toolkit:DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <DataTemplate.Resources>
                    <ui:Converter x:Key="Converter" />
                </DataTemplate.Resources>
                <StackPanel>
                    <CheckBox Content="Apple" IsChecked="{Binding Path=Fruits, Converter={StaticResource Converter}, ConverterParameter={x:Static constants:Fruits.Apple}}" />
                    <CheckBox Content="Orange" IsChecked="{Binding Path=Fruits, Converter={StaticResource Converter}, ConverterParameter={x:Static constants:Fruits.Orange}}" />
                    <CheckBox Content="Peach" IsChecked="{Binding Path=Fruits, Converter={StaticResource Converter}, ConverterParameter={x:Static constants:Fruits.Peach}}" />
                </StackPanel>
            </DataTemplate>
        </toolkit:DataGridTemplateColumn.CellTemplate>
    </toolkit:DataGridTemplateColumn>
</toolkit:DataGrid.Columns>

When I load the binding from the object, it goes through Convert for each item in the list (an ObservableCollection) and binds the checkboxes correctly, and stores them in the target field. However, when I check/uncheck another box, the target field is defaulted to "None" and the behavior is as if you're starting over from scratch.

Any help?

Community
  • 1
  • 1
sohum
  • 3,207
  • 2
  • 39
  • 63

2 Answers2

3

Where is the "Converter" resource defined? At what scope? It would have to be defined at the scope of your items template if you've got a list of items because it needs to maintain state for each item individually.

Drew Marsh
  • 33,111
  • 3
  • 82
  • 100
  • It's defined in the DataTemplate.Resources section of the DataGridTemplateColumn. Is that the same thing? I'll update the question with the code. – sohum Nov 10 '09 at 14:55
  • I have updated the code. Like I said, the binding does work on the first time through. However, once I close and restart the application and load the bindings from the database, it binds them correctly on load but seems to lose these values after that. – sohum Nov 10 '09 at 15:01
  • Hmm... ya know what, I forget off the top of my head whether or not the resources for a template are shared amongst instances and I don't have time to test right this second. Can you try moving the converter into the resources of the instead really quick??? – Drew Marsh Nov 10 '09 at 15:22
  • Great, glad we could figure it out! – Drew Marsh Nov 11 '09 at 13:26
1

I might be off-base here, but could it be because your enum defines "Three" as 3?

Since you're using bitwise operators to check and uncheck the checkboxes, the "Three" value (0x11) will correspond to both the "One" and "Two" values (0x01 and 0x10 respectively).

I know it seems counter-intuitive, but try changing your enum declaration to:

enum Numbers : int { One = 1, Two = 2, Three = 4, None = 0 };
Matt Hamilton
  • 200,371
  • 61
  • 386
  • 320
  • My bad. I rewrote the original code since I didn't want to share it. There are actually 16 enums and they are all powers of 2. Sorry about that! – sohum Nov 02 '09 at 05:39
  • I think the issue may be that the IValueConverter is getting reinitialized for some reason. How could I go about checking this? – sohum Nov 09 '09 at 20:50
  • I can't imagine it would be, but I suppose you could create a parameterless constructor and put a breakpoint in it test your theory. – Matt Hamilton Nov 09 '09 at 21:15