【问题标题】:Bool To Image Converter not displaying image at Design Time布尔到图像转换器在设计时不显示图像
【发布时间】:2018-11-29 21:13:07
【问题描述】:

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

转换器:

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

【问题讨论】:

  • 您正在使用 roll_feed_closed.png 和 roll_feed_opened.png 覆盖 xaml 中的图像值。您需要在那里使用 pack 语法。只是一些友好的建议,但我会学习 MVVM 和正确的 WPF 数据绑定。您正在按照代码的结构方式陷入困境。更好的方法是使用触发器。
  • “包语法”部分不正确。 XAML 解析器将自动添加缺少的 Uri 组件。并且“转换器在运行时完美运行”。
  • 我根本不会使用绑定转换器来执行此操作。您可能会更好地在 SomeBoolValue 上使用带有 DataTrigger 的 Image Style,并为 Source 属性使用 Setter。
  • 同意你应该使用触发器,这里根本不需要转换器。
  • 感谢 cmets。这只是问题的一个简单示例,或者更确切地说是我试图更好地理解的问题。我同意,如果这就是我想要完成的全部,那么带有一些触发器的风格会更直接。我实际上是在一个自定义控件上使用这个转换器,该控件已经具有与之关联的样式,以及它自己的 ImageSource 类型的 Image 属性。我使用转换器的正是这个属性。

标签: c# wpf


【解决方案1】:

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

<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>

【讨论】:

    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2013-07-21
      • 1970-01-01
      • 1970-01-01
      • 2014-11-26
      • 2014-06-13
      • 2019-06-13
      • 2017-03-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多