WPF—编程宝典P1
1,WPF主要结构
2,XAML标记扩展
扩展标记工作流程:
1,首先,建立扩展标记的类对象实列
<MenuItem.Icon> <Image Stretch="Uniform" Source="{extension:ImageBinding Redo}"></Image> </MenuItem.Icon>
2,建立类的实列,并且运行,注意里面的ConstructorArgument.属性.可以用来默认构造函数.
然后调用ProvideValue方法进行数据解析,并且返回需要的数据.这里是Image.Source返回一个BitmapImage,注意,
如果是在Style的Setter中进行调用,那么,其只返回绑定.
在这里,其首先建立绑定Binding对象,因为根据DataContext,其会在对应的ViewModel里面来寻找合适的数据.然后,由于Binding也是
一个MarkUpExtension,所以可以利用其ProvideValue来返回需要的值.注意,Binding 的Converter 其实等价于在Xaml中进行如下的编写:
<Image Stretch="Uniform" Source="{Binding SaveAll,Converter={StaticResource SourceConverter}}"></Image> </MenuItem.Icon>
public class ImageBindingExtension : System.Windows.Markup.MarkupExtension { public ImageBindingExtension(string path) : this() { Path = path; } public ImageBindingExtension() { } [ConstructorArgument("path")] public string Path { get; set; } public override object ProvideValue(IServiceProvider serviceProvider) { IProvideValueTarget target = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget; if (target.TargetObject is Setter) { return new Binding(Path) { Converter = ImgaeSourceConverter.Default }; } else { Binding binding = new Binding(Path) { Converter = ImgaeSourceConverter.Default }; return binding.ProvideValue(serviceProvider); } } }
然后,来谈一谈 serviceProvider对象,其具有GetService(type) 函数,来返回服务的对象.
public interface IServiceProvider { // // 摘要: // 获取指定类型的服务对象。 // // 参数: // serviceType: // 一个对象,它指定要获取的服务对象的类型。 // // 返回结果: // serviceType 类型的服务对象。 或 - 如果没有 serviceType 类型的服务对象,则为 null。 object GetService(Type serviceType); }
常见的一些服务:
- ITypeDescriptorContext 包含了 Container,Instance,PropertyDescriptor
- IProvideValueTarget 包含了 TargetObject---Image,TargetProperty---Source.
- IUriContext--BaseUri包含了所在xaml的路径
- IRootObjectProvider---RootObject当前窗口.
3,另外的一个列子
该例子使用扩展标记来反射查看一个类的信息
<TextBlock Text="反射获取Button的方法、字段、事件" /> <ListBox MaxHeight="200" Margin="0,2" HorizontalAlignment="Stretch" VerticalAlignment="Top" ItemsSource="{extension:Reflection {x:Type Button}, IncludeMethods=true, IncludeFields=true, IncludeEvents=true}" />
public class ReflectionExtension : System.Windows.Markup.MarkupExtension { public Type CurrentType { get; set; } public bool IncludeMethods { get; set; } public bool IncludeFields { get; set; } public bool IncludeEvents { get; set; } public ReflectionExtension(Type currentType) { this.CurrentType = currentType; } public override object ProvideValue(IServiceProvider serviceProvider) { if (this.CurrentType == null) { throw new ArgumentException("Type argument is not specified"); } List<string> collection = new List<string>(); foreach (PropertyInfo p in this.CurrentType.GetProperties()) { collection.Add(string.Format("属性 : {0}", p.Name)); } if (this.IncludeMethods) { foreach (MethodInfo m in this.CurrentType.GetMethods()) { collection.Add(string.Format("方法 : {0} with {1} argument(s)", m.Name, m.GetParameters().Count())); } } if (this.IncludeFields) { foreach (FieldInfo f in this.CurrentType.GetFields()) { collection.Add(string.Format("字段 : {0}", f.Name)); } } if (this.IncludeEvents) { foreach (EventInfo e in this.CurrentType.GetEvents()) { collection.Add(string.Format("事件 : {0}", e.Name)); } } return collection; } }
案列位置 C:\RepsOutSide\WPF研究案列\WpfMarkupExtensionDemo