开发者

Adding IValueConverter breaks updates when changed occur from observable collection to UI

I have a itemscontrol with the item template set to a border, then i bind the datacontext of the listview to a list of objects that contain a bool property.

Then i added a click event handler to the border, and when detecting a click, i cast the datacontext of the border to the class and set the bool field to true.

That works as a charm, but i want the rectangle to have a specific colour when the bool field is set to true or false, so i created a IValueConverter that takes my class and returns a colour. That works too, the rectangles are different colors based on the bool field.

I am still able to click the rectangles, but they just arent updated. The color of the rectangle wont change.

Datatemplate from the itemscontrol itemtemplate

            <DataTemplate>
                <Border ToolTip="{Binding Seat.Column}" Width="25" Height="25" Margin="0,0,2,2" BorderBrush="Black" Background="{Binding Converter={StaticResource ResourceKey=SeatStateConverter}}" BorderThickness="2" Name="rectangle1" VerticalAlignment="Center" HorizontalAlignment="Center" MouseLeftButtonDown="rectangle1_MouseLeftButtonDown">
                    <Label Content="{Binding Occupied}" Foreground="White" FontSize="7"></Label>
                </Border>
            </DataTemplate>

The click event

    private void rectangle1_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        Border item = sender as Border;
        SeatState state = item.DataContext as SeatState;

        state.Locked = !state.Locked;
    }

my converter

        public object Convert(object value, Type targetType, object parameter,   System.Globalization.CultureInfo culture)
        {
            SeatState state = value as SeatState;
            if (state == null)
                return null;

            SolidColorBrush brush = new SolidColorBrush();

            if (state.Occupied)
            {
                brush.Color = Color.FromRgb(172, 0,0);
            }
            else if (state.Locked)
            {
                brush.Color = Color.FromRgb(214, 65, 0);
            }
            else if(!state.Occupied)
       开发者_如何学C     {
                brush.Color = Color.FromRgb(0, 172, 0);
            }

            return brush;
        }

This works great.. untill i add the converter that converts the objects into a SolidColorBrush.

I tried all sorts of crazy stuff that should have nothing to do with my problem.

  • implementing the convertback method in the IValueConverter interface
  • setting the binding to a two way binding
  • invoking the UpdateLayout method on the ItemsControl

But nothing seemed to work.

Anyone got any ideas? My english could be better so please ask if there is anything you want clearified =)

Thanks in advance.


I think you are binding to the SeatState object - whereas you actually need to bind to some combination of the Occupied an Locked properties?

i.e. it's not the SeatState object itself that is changing, but rather its a couple of the properties of the SeatState.

Maybe merge the properties together somehow and set this merged property as the Path for the XAML Background.

e.g. within SeatState

private bool _Locked
public bool Locked
{
get
{
   return _Locked;
}
set
{
   _Locked = value;
   NotifyPropertyChange("Locked");
   NotifyPropertyChange("LockedAndOccupied");
}
}

private bool _Occupied
public bool Occupied
{
get
{
   return _Occupied;
}
set
{
   _Occupied = value;
   NotifyPropertyChange("Occupied");
   NotifyPropertyChange("LockedAndOccupied");
}
}

public Tuple<bool, bool> LockedAndOccupied
{
   get
   {
       return new Tuple<bool, bool>(Locked, Occupied);
   }
}

then in the XAML you can bind to Path=LockedAndOccupied, Converter=...

Obviously you'll have to change the Converter code too - I'll let you do that!


Alternatively... now I've read up about it...

There is something called a MultiBinding - http://www.switchonthecode.com/tutorials/wpf-tutorial-using-multibindings - looks perfect for your needs

Something like:

<Border.Background>
<MultiBinding Converter="{StaticResource aNewConverter}">
   <Binding Path="Locked"/>
   <Binding Path="Occupied"/>
</MultiBinding> 
</Border.Background>

I've learnt something new tonight :)


Check the Background binding... it looks like your Path is missing. I would expect to see something like...

Background="{Binding Path=., Converter={StaticResource ResourceKey=SeatStateConverter}}"

Alternately you could try setting BindsDirectlyToSource=true.

On second thought, you probably need to implement an IMultiValueConverter, and then bind each of the properties separately. That may be what you need to do to get the change notifications on each of the properties. Here is an example of an IMultiValueConverter implementation from MSDN.

Also, you may want to check your implementation of INotifyPropertyChanged... misspellings of property names will break the change notifications...

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜