简体   繁体   中英

Data Binding + Converter doesn't update bound property - XAML - WPF

What I want:

Binding an observable collection to a property (eg Opacity ) which should take the returned value of a converter class.


The XAML code:

    <ListBox x:Name="HostDeviceList" 
            ItemsSource="{Binding ObservableCollection}" 
            SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
            ScrollViewer.HorizontalScrollBarVisibility="Disabled">
    <ListBox.Background>
        <ImageBrush ImageSource="assets/Tapako.ico" 
                    Opacity="{Binding ObservableCollection, Converter={StaticResource IsNullToFloatConverter}}" Stretch="None">
        </ImageBrush>
    </ListBox.Background>

My Converter Class:

public class IsNullToFloatConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
    float lowValue = 0.1f;
    float highValue = 0.5f;

    if (parameter is float && value != null)
    {
        return parameter;
    }
    else
    {
        if (value is IEnumerable)
        {
            if (((IEnumerable)value).Any())
            {
                return lowValue;
            }
            else
            {
                return highValue;
            }
        }
        if (value != null)
        {
            return lowValue;
        }
        else
        {
            return highValue;
        }
    }
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
    throw new NotImplementedException();
}
}

What works:

  1. The ListView is correctly updated
  2. If I dont't use a converter class but use Opacity="{Binding ObservableCollection.Count}" the opacity changes from 0 to 1 as soon as the first element appars

What doesn't work: If I use the converter, the Convert is just called once at startup but isn't called while new elements appear in the ListView

Most probably your collection is not changing (I mean the reference to your collection) so you have to implement mechanism to handle the collection changed event instead (which fires when values are added or removed)

Note: In both cases you need to change the converter to work with the count directly

So you should be able to to it like this , if it doesn't works out -> meaning the collection doesn't notify when it's count changes you go the longer road described below:

<ImageBrush ImageSource="assets/Tapako.ico" 
            Opacity="{Binding ObservableCollection.Count, Converter={StaticResource IsNullToFloatConverter}}" Stretch="None">
</ImageBrush>

I would do that like this if the above doesn't work:

Create a new property -> to which I will bind CollectionCount in the VM

public int collectionCount;

public int CollectionCount
{
    get
    {
        return collectionCount;
    }
    set
    {
        collectionCount = value;
        RaisePropertyChanged("CollectionCount");
    }
} 

Change your binding to use it instead of the whole collection

<ImageBrush ImageSource="assets/Tapako.ico" 
            Opacity="{Binding CollectionCount, Converter={StaticResource IsNullToFloatConverter}}" Stretch="None">
</ImageBrush>

Register for collection changes and create a handler that will give the count to your property which will then fire on change and call the converter

ObservableCollectionProp.CollectionChanged += CollectionChangedHandler;

private void CollectionChangedHandler(object sender, NotifyCollectionChangedEventArgs e)
{
    CollectionCount = ObservableCollectionProp.Count;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM