WPF—编程宝典P1

摘要:
////返回result://serviceType服务对象。如果没有serviceType类型的服务对象,则为null。

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:RepsOutSideWPF研究案列WpfMarkupExtensionDemo

免责声明:文章转载自《WPF—编程宝典P1》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Postfix+Amavisd-new+Spamassassin+ClamAV整合安装python-mysql数据迁移下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

8天入门wpf(转)

8天入门wpf—— 第一天 基础概念介绍8天入门wpf—— 第二天 xaml详解8天入门wpf—— 第三天 样式8天入门wpf—— 第四天 模板8天入门wpf—— 第五天 数据绑定8天入门wpf—— 第六天 细说控件8天入门wpf—— 第七天 画刷8天入门wpf—— 第八天 最后的补充WPF 一个MVVM的简单例子 MVVM设计模式...

WPF中TreeView控件的使用案例

WPF总体来说还是比较方便的,其中变化最大的主要是Listview和Treeview控件,而且TreeView似乎在WPF是一个备受指责的控件,很多人说他不好用。我这个demo主要是在wpf中使用TreeView控件实现图片查看功能,简单的Grid布局、TreeView控件添加图标、TreeView控件的一些事件、显示统计、还有就是读取文件操作。 效果图:...

WPF DataGrid多选功能开发

<DataTemplate x:Key="CheckBoxDataTemplate"> <Grid x:Name="Grid" HorizontalAlignment="Center" VerticalAlignment="Center"> <CheckBox...

wpf中遍历界面控件的方法

/// <summary>/// 遍历界面中的所有控件/// </summary>/// <param name="uiControls"></param>private void SetNotEditable(UIElementCollection uiControls){foreach (UIElemen...

WPF 同一窗口内的多线程 UI(VisualTarget)

WPF 的 UI 逻辑只在同一个线程中,这是学习 WPF 开发中大家几乎都会学习到的经验。如果希望做不同线程的 UI,大家也会想到使用另一个窗口来实现,让每个窗口拥有自己的 UI 线程。然而,就不能让同一个窗口内部使用多个 UI 线程吗? 答案其实是——可以的!使用 VisualTarget 即可。 阅读本文将收获一份对 VisualTarget 的解读以...

WPF DesiredSize &amp;amp; RenderSize

DesiredSize DesiredSize介绍 关于DesiredSize的介绍,可以查看最新微软文档对DesiredSize的介绍 DesiredSize,指的是元素在布局过程中计算所需要的大小。 通过调用方法Measure计算得到DesiredSize 1 element.Measure(availableSize); 2 var desi...