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
}
}
答案 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设计器中返回我想要的图像。