布尔到图像转换器在设计时不显示图像

时间:2018-11-29 21:13:07

标签: c# wpf

BoolToImage转换器在运行时运行完美,根据绑定到布尔属性的绑定更改Image对象的ImageSource,该布尔属性在单击按钮时被切换。在设计时,VS设计器将不会显示转换器返回的图像。为什么? TrueImageProperty和FalseImageProperty是静态的,并且具有默认值。为什么至少没有默认的ImageSource返回并显示在VS设计器中??

转换器:

namespace BoolToImageConverterTestApp
{
[ValueConversion (typeof (bool), typeof (ImageSource))]
public class BoolToImageConverter : DependencyObject, IValueConverter
{
    public static readonly DependencyProperty TrueImageProperty = DependencyProperty.Register ("TrueImage", typeof (ImageSource), typeof (BoolToImageConverter), new UIPropertyMetadata ((ImageSource)new BitmapImage (new Uri ("pack://application:,,,/BoolToImageConverterTestApp;component/green_led.png", UriKind.RelativeOrAbsolute))));
    public static readonly DependencyProperty FalseImageProperty = DependencyProperty.Register ("FalseImage", typeof (ImageSource), typeof (BoolToImageConverter), new UIPropertyMetadata ((ImageSource)new BitmapImage (new Uri ("pack://application:,,,/BoolToImageConverterTestApp;component/gray_led.png", UriKind.RelativeOrAbsolute))));

    public ImageSource TrueImage
    {
        get { return (ImageSource)GetValue (TrueImageProperty); }
        set { SetValue (TrueImageProperty, value); }
    }

    public ImageSource FalseImage
    {
        get { return (ImageSource)GetValue (FalseImageProperty); }
        set { SetValue (FalseImageProperty, value); }
    }

    private const string Invert = "Invert";

    public object Convert (object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if ( targetType != typeof (ImageSource) )
            throw new InvalidOperationException ("The target must be a ImageSource");

        if ( (value == null) || (value == DependencyProperty.UnsetValue) )
        {
            if ( FalseImage != null )
                return FalseImage;
            else
                return DependencyProperty.UnsetValue;
        }

        bool? bValue = (bool?)value;

        if ( (parameter != null) && ((parameter as string) == Invert) )
            bValue = !bValue;

        if ( bValue.Value )
        {
            if ( TrueImage != null )
                return this.TrueImage;
        }
        else
        {
            if ( FalseImage != null )
                return this.FalseImage;
        }

        return DependencyProperty.UnsetValue;
    }

    public object ConvertBack (object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException ("BoolToImageConverter ConvertBack not implemented - use OneWay binding");
    }
}

}

测试应用XAML:

<Window x:Class="BoolToImageConverterTestApp.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     xmlns:local="clr-namespace:BoolToImageConverterTestApp"
    Title="MainWindow" Height="350" Width="525">

<Window.Resources>
    <local:BoolToImageConverter x:Key="RollFeedImageConverter" TrueImage="roll_feed_closed.png" FalseImage="roll_feed_opened.png"/>
</Window.Resources>

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition  Height="*"/>
        <RowDefinition  Height="*"/>
    </Grid.RowDefinitions>

    <Image x:Name="TestImage" Grid.Row="0" Source="{Binding Path=SomeBoolValue, Converter={StaticResource RollFeedImageConverter}, Mode=OneWay}" Stretch="None"/>
    <Button x:Name="TestButton" Grid.Row="1" Content="Toggle Image" Margin="20" Click="TestButton_Click"/>
</Grid>

测试应用代码背后:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;

namespace BoolToImageConverterTestApp
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window, INotifyPropertyChanged
{
    public MainWindow ()
    {
        DataContext = this;
        InitializeComponent ();
    }

    public bool SomeBoolValue
    {
        get { return _someBoolValue; }
        set
        {
            if ( _someBoolValue != value )
            {
                _someBoolValue = value;
                RaisePropertyChanged ("SomeBoolValue");
            }
        }
    }
    private bool _someBoolValue = false;

    private void TestButton_Click (object sender, RoutedEventArgs e)
    {
        SomeBoolValue ^= true;
    }

    #region INotifyPropertyChanged implementation

    /// <summary>
    /// Raises the PropertyChange event for the property specified
    /// </summary>
    /// <param name="propertyName">Property name to update. Is case-sensitive.</param>
    public virtual void RaisePropertyChanged (string propertyName)
    {
        OnPropertyChanged (propertyName);
    }

    /// <summary>
    /// Raised when a property on this object has a new value.
    /// </summary>
    public event PropertyChangedEventHandler PropertyChanged;

    /// <summary>
    /// Raises this object's PropertyChanged event.
    /// </summary>
    /// <param name="propertyName">The property that has a new value.</param>
    protected virtual void OnPropertyChanged (string propertyName)
    {
        PropertyChangedEventHandler handler = this.PropertyChanged;
        if ( handler != null )
        {
            var e = new PropertyChangedEventArgs (propertyName);
            handler (this, e);
        }
    }

    #endregion // INotifyPropertyChanged implementation
}
}

项目布局: enter image description here

2 个答案:

答案 0 :(得分:0)

您不需要转换器,只需使用这样的触发器即可:

<Image x:Name="TestImage" Grid.Row="0" Stretch="None">
    <Image.Style>
        <Style TargetType="Image">
            <Setter Property="Source" Value="roll_feed_opened.png"/>
            <Style.Triggers>
                <DataTrigger Binding="{Binding SomeBoolValue}" Value="True">
                    <Setter Property="Source" Value="roll_feed_closed.png"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Image.Style>
</Image>

答案 1 :(得分:0)

感谢您的想法。我真的只想尝试了解设计时与运行时会发生什么。为什么转换器至少不返回依赖属性的默认图像?在设计时是否不会创建资源?窗口的构造函数是否不会在设计时调用,因此不会设置DataContext?我只是在学习设计时d:DataContext和d:DesignData和d:DesignInstance。实际上,使用d:DesignInstance可以让转换器在VS设计器中返回我想要的图像。