WPF—编程宝典P1

1,WPF主要结构

image

2,XAML标记扩展

image

扩展标记工作流程:


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);
    }

常见的一些服务:

image

  • 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

posted @ 2021-05-07 14:54  frogkiller  阅读(392)  评论(0编辑  收藏  举报