Silverlight 使用Caliburn.Micro将图像绑定到Uri
为什么下面的图像不能正确绑定到源Silverlight 使用Caliburn.Micro将图像绑定到Uri,silverlight,caliburn.micro,Silverlight,Caliburn.micro,为什么下面的图像不能正确绑定到源 <UserControl x:Class="SlCaliburnConventionTest.Sample" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expr
<UserControl x:Class="SlCaliburnConventionTest.Sample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<Grid x:Name="LayoutRoot" Background="White">
<Image x:Name="UriProperty" />
</Grid>
</UserControl>
我深入研究了Caliburn.Micro源代码,发现它在应用约定时没有使用TypeDescriptor。问题是:我们如何说服Caliburn.Micro将URI转换为ImageSource?图像控件演示了XAML的一个有趣特性,即类型转换。例如,图像的XAML api如下所示:
<Image Source="http://lorempixel.com/100/100/people" />
class Image {
ImageSource Source { get; set;}
DependencyProperty SourceProperty // etc.
}
字符串是如何转换成Uri,然后转换成ImageSource的
答案在于类型转换器
[TypeConverter(typeof(ImageSourceConverter))]
public class ImageSource {}
当我们以编程方式创建到Uri的绑定时,上面的魔法不会发生。结果是没有显示任何图片
// No picture is shown.
BindingOperations.SetBinding(myImage,
Image.SourceProperty, new Binding("MyUri"));
同样,我们不能这样做:
// compile time error
myImage.Source = new Uri("http://...")
相反,正确的方法是从ImageSource的自定义属性中获取类型转换器,并将其转换为IValueConverter。这是我的-主要工作由这一行公共对象转换(…)
执行-其他一切都是脚手架:
namespace Caliburn.Micro
{
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
public class ValueTypeConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var result = TypeDescriptor.GetConverter(targetType).ConvertFrom(value);
return result;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
/// <summary>
/// Binding Image.Source to an Uri typically fails.
/// Calling the following during application bootstrap will set this up properly.
/// ConventionManager.ApplyValueConverter = ValueTypeConverter.ApplyValueConverter;
/// </summary>
/// <param name="binding"></param>
/// <param name="bindableProperty"></param>
/// <param name="info"></param>
public static void ApplyValueConverter(Binding binding, DependencyProperty bindableProperty, PropertyInfo info)
{
if (bindableProperty == UIElement.VisibilityProperty && typeof(bool).IsAssignableFrom(info.PropertyType))
binding.Converter = ConventionManager.BooleanToVisibilityConverter;
else if (bindableProperty == Image.SourceProperty && typeof(Uri).IsAssignableFrom(info.PropertyType))
binding.Converter = new ValueTypeConverter();
else
{
foreach (var item in _Conventions)
{
if (bindableProperty == item.Item1 && item.Item2.IsAssignableFrom(info.PropertyType))
binding.Converter = new ValueTypeConverter();
}
}
}
/// <summary>
/// If there is a TypeConverter that can convert a <paramref name="SourceType"/>
/// to the type on <paramref name="bindableProperty"/>, then this has to
/// be manually registered with Caliburn.Micro as Silverlight is unable to
/// extract sufficient TypeConverter information from a dependency property
/// on its own.
/// </summary>
/// <example>
/// ValueTypeConverter.AddTypeConverter<ImageSource>(Image.SourceProperty);
/// </example>
/// <typeparam name="SourceType"></typeparam>
/// <param name="bindableProperty"></param>
public static void AddTypeConverter<SourceType>(DependencyProperty bindableProperty)
{
_Conventions.Add(Tuple.Create<DependencyProperty, Type>(bindableProperty, typeof(SourceType)));
}
private static IList<Tuple<DependencyProperty, Type>> _Conventions = new List<Tuple<DependencyProperty, Type>>();
}
}
图像控件演示了XAML的一个有趣属性,即类型转换。例如,图像的XAML api如下所示:
<Image Source="http://lorempixel.com/100/100/people" />
class Image {
ImageSource Source { get; set;}
DependencyProperty SourceProperty // etc.
}
字符串是如何转换成Uri,然后转换成ImageSource的
答案在于类型转换器
[TypeConverter(typeof(ImageSourceConverter))]
public class ImageSource {}
当我们以编程方式创建到Uri的绑定时,上面的魔法不会发生。结果是没有显示任何图片
// No picture is shown.
BindingOperations.SetBinding(myImage,
Image.SourceProperty, new Binding("MyUri"));
同样,我们不能这样做:
// compile time error
myImage.Source = new Uri("http://...")
相反,正确的方法是从ImageSource的自定义属性中获取类型转换器,并将其转换为IValueConverter。这是我的-主要工作由这一行公共对象转换(…)
执行-其他一切都是脚手架:
namespace Caliburn.Micro
{
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
public class ValueTypeConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var result = TypeDescriptor.GetConverter(targetType).ConvertFrom(value);
return result;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
/// <summary>
/// Binding Image.Source to an Uri typically fails.
/// Calling the following during application bootstrap will set this up properly.
/// ConventionManager.ApplyValueConverter = ValueTypeConverter.ApplyValueConverter;
/// </summary>
/// <param name="binding"></param>
/// <param name="bindableProperty"></param>
/// <param name="info"></param>
public static void ApplyValueConverter(Binding binding, DependencyProperty bindableProperty, PropertyInfo info)
{
if (bindableProperty == UIElement.VisibilityProperty && typeof(bool).IsAssignableFrom(info.PropertyType))
binding.Converter = ConventionManager.BooleanToVisibilityConverter;
else if (bindableProperty == Image.SourceProperty && typeof(Uri).IsAssignableFrom(info.PropertyType))
binding.Converter = new ValueTypeConverter();
else
{
foreach (var item in _Conventions)
{
if (bindableProperty == item.Item1 && item.Item2.IsAssignableFrom(info.PropertyType))
binding.Converter = new ValueTypeConverter();
}
}
}
/// <summary>
/// If there is a TypeConverter that can convert a <paramref name="SourceType"/>
/// to the type on <paramref name="bindableProperty"/>, then this has to
/// be manually registered with Caliburn.Micro as Silverlight is unable to
/// extract sufficient TypeConverter information from a dependency property
/// on its own.
/// </summary>
/// <example>
/// ValueTypeConverter.AddTypeConverter<ImageSource>(Image.SourceProperty);
/// </example>
/// <typeparam name="SourceType"></typeparam>
/// <param name="bindableProperty"></param>
public static void AddTypeConverter<SourceType>(DependencyProperty bindableProperty)
{
_Conventions.Add(Tuple.Create<DependencyProperty, Type>(bindableProperty, typeof(SourceType)));
}
private static IList<Tuple<DependencyProperty, Type>> _Conventions = new List<Tuple<DependencyProperty, Type>>();
}
}
我使用字符串作为支持属性,绑定适用于我:
public class TestViewModel : ViewModelBase
{
public TestViewModel()
{
ImageUrl = "http://cdn.sstatic.net/stackoverflow/img/apple-touch-icon.png";
}
public string ImageUrl { get; set; }
}
<Image Source="{Binding ImageUrl}" />
公共类TestViewModel:ViewModelBase
{
公共TestViewModel()
{
ImageUrl=”http://cdn.sstatic.net/stackoverflow/img/apple-touch-icon.png";
}
公共字符串ImageUrl{get;set;}
}
我使用字符串作为支持属性,绑定对我有效:
public class TestViewModel : ViewModelBase
{
public TestViewModel()
{
ImageUrl = "http://cdn.sstatic.net/stackoverflow/img/apple-touch-icon.png";
}
public string ImageUrl { get; set; }
}
<Image Source="{Binding ImageUrl}" />
公共类TestViewModel:ViewModelBase
{
公共TestViewModel()
{
ImageUrl=”http://cdn.sstatic.net/stackoverflow/img/apple-touch-icon.png";
}
公共字符串ImageUrl{get;set;}
}
Caliburn不允许只写
?在我看来要容易得多。请注意,强迫意味着不同的东西。你的意思是所谓的类型转换。在这两方面你都是对的。谢谢实际上,我正在研究使用类型转换来显示用户可以替换的图像,因为这似乎是隐藏大部分相关复杂性的好方法。Caliburn不允许简单地编写
?在我看来要容易得多。请注意,强迫意味着不同的东西。你的意思是所谓的类型转换。在这两方面你都是对的。谢谢实际上,我正在研究如何使用类型转换来显示用户可以替换的图像,因为这似乎是一种很好的方法来隐藏与此相关的复杂性。谢谢Rob。我特别想了解如何使用Caliburn.Micro使类型转换器工作。谢谢Rob。我特别想了解如何使类型转换器与Caliburn.Micro一起工作。