Refreshing a binding that uses a value converter

2019-02-25 12:28发布

I have a WPF UI that is bound to an object. I'm using a ValueConverter to convert a property to a specific image by a business rule:


    public class ProposalStateImageConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var proposal = value as Proposal;
            var basePath = "pack://application:,,,/ePub.Content;component/Images/General/Flag_{0}.png";
            string imagePath;

            if(proposal.Invoice != null)
            {
                imagePath = string.Format(basePath, "Good");
            }
            else
            {
                imagePath = string.Format(basePath, "Warning");
            }

            var uri = new Uri(imagePath);
            var src = uri.GetImageSource(); //Extention method

            return src;
        }
    }

The element is a TreeView where the image is on the 2nd level:


    <TreeView x:Name="tree"
              ItemsSource="{Binding People}" 
              SelectedItemChanged="OnTreeItemChanged">
        <TreeView.Resources>
            <HierarchicalDataTemplate DataType="{x:Type dmn:Person}" 
                                      ItemsSource="{Binding Proposals}">
                <StackPanel Orientation="Horizontal" ToolTip="{Binding Path=Fullname}" Margin="3">
                    <Image Margin="5,0,5,0" Width="16" Height="16" Source="pack://application:,,,/ePub.Content;component/Images/General/Person_Active.png" />
                    <TextBlock Text="{Binding Path=Firstname}" />
                    <TextBlock Text="{Binding Path=Lastname}" Margin="5,0,0,0" />
                </StackPanel>
            </HierarchicalDataTemplate>
            <HierarchicalDataTemplate DataType="{x:Type dmn:Proposal}">
                <StackPanel Orientation="Horizontal" Margin="3">
                    <Image x:Name="invoiceImage" Width="16" Height="16" Margin="5,0,5,0" Source="{Binding, Converter={StaticResource ProposalStateImageConverter}, UpdateSourceTrigger=PropertyChanged}" />
                    <TextBlock Text="{Binding DeliveryDate, Converter={StaticResource textCulturedDateConverter}}" />
                </StackPanel>
            </HierarchicalDataTemplate>
        </TreeView.Resources>
    </TreeView>

It is working fine, but later, when the object's state changes, I want to refresh the image and make the value converter reevaluate. How is this possible?

2条回答
劳资没心,怎么记你
2楼-- · 2019-02-25 13:19

It looks like you're only using a single value inside the converter and you're just doing a simple switch between two values so you could instead just do this directly in XAML with a trigger. This method also switches to a Binding against the Invoice property so that any change notifications for that property will cause the Trigger to update.

<HierarchicalDataTemplate >
    <StackPanel Orientation="Horizontal" Margin="3">
        <Image x:Name="invoiceImage" Width="16" Height="16" Margin="5,0,5,0" Source="good.png"/>
        <TextBlock ... />
    </StackPanel>
    <HierarchicalDataTemplate.Triggers>
        <DataTrigger Binding="{Binding Invoice}" Value="{x:Null}">
            <Setter TargetName="invoiceImage" Property="Source" Value="warning.png"/>
        </DataTrigger>
    </HierarchicalDataTemplate.Triggers>
</HierarchicalDataTemplate>
查看更多
地球回转人心会变
3楼-- · 2019-02-25 13:32

Assuming you can't use INotifyPropertyChanged because you're binding to the whole object, you need to call BindingExpression.UpdateTarget.

The slight subtlety is in getting hold of the binding expression. This requires you to have a fairly intimate knowledge of the view: as far as I know, the only way to do this is to call BindingOperations.GetBindingExpression, passing the control and property whose binding you want to update, e.g.:

BindingOperations.GetBindingExpression(myImage, Image.SourceProperty).UpdateTarget();
查看更多
登录 后发表回答