WPF 自定义几种 MarkupExtension

11 篇文章 0 订阅

MarkupExtension

详见: MarkupExtension.

#region 程序集 WindowsBase.dll, v3.0.0.0
// C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\WindowsBase.dll
#endregion
 
using System;
 
namespace System.Windows.Markup
{
    // 摘要:
    //     为所有 XAML 标记扩展提供基类。
    public abstract class MarkupExtension
    {
        // 摘要:
        //     初始化从 System.Windows.Markup.MarkupExtension 派生的类的新实例。
        protected MarkupExtension();
 
        // 摘要:
        //     在派生类中实现时,返回一个对象,此对象被设置为此标记扩展的目标属性的值。
        //
        // 参数:
        //   serviceProvider:
        //     可以为标记扩展提供服务的对象。
        //
        // 返回结果:
        //     将在扩展应用到的属性上设置的对象值。
        public abstract object ProvideValue(IServiceProvider serviceProvider);
    }
}  

Bool2ColorConverter

实现Bool? 对应三种颜色状态变化。 可以扩展到枚举对象的颜色状态变化

#region  << 版 本 注 释 >>
/*
 * ----------------------------------------------------------------
 * Copyright @ Daniel大妞 2021. All rights reserved.
 
 * 作    者 :Daniel大妞 (Daniel)
 
 * 创建时间 :2021/6/11 17:25:35
 
 * CLR 版本 :4.0.30319.42000
 
 * 命名空间 :DN.Controls.Markup
 
 * 类 名 称 :ColorChangedExtension

 * 类 描 述 :
 
 * ------------------------------------------------------
 * 历史更新记录
 
 * 版本 :  V1.0.0.0        修改时间:2021/6/11 17:25:35         修改人:Daniel大妞 (Daniel)
 
 * 修改内容:
 * 
 */
#endregion

using System;
using System.Globalization;
using System.Windows.Data;
using System.Windows.Markup;
using System.Windows.Media;

namespace DN.Controls.Converters
{
    public class Bool2ColorConverter : MarkupExtension, IValueConverter
    {
        private static readonly Brush MS_Red = new SolidColorBrush(Colors.Red);
        private static readonly Brush MS_Green = new SolidColorBrush(Colors.Green);
        private static readonly Brush MS_Blue = new SolidColorBrush(Colors.Blue);

        public Brush BrushWhenTrue { get; set; } = MS_Red;
        public Brush BrushWhenNull { get; set; } = MS_Green;
        public Brush BrushWhenFalse { get; set; } = MS_Blue;

        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value == null)
            {
                return this.BrushWhenNull;
            }
            else if ((bool)value)
            {
                return this.BrushWhenTrue;
            }
            else
            {
                return this.BrushWhenFalse;
            }
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }

        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            return this;
        }
    }
}

用法:

<Window
    x:Class="wpf.Bool2ColorExtensionTest.MainWindow"
    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:local="clr-namespace:wpf.Bool2ColorExtensionTest"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Title="MainWindow"
    Width="800"
    Height="450"
    mc:Ignorable="d">
    <Grid>
        <CheckBox
            x:Name="PART_SSS"
            Width="100"
            Height="100"
            IsThreeState="True" />
        <Button
            Width="200"
            Height="200"
            Margin="30,0,0,0"
            HorizontalAlignment="Left"
            Background="{Binding ElementName=PART_SSS, Path=IsChecked, Converter={local:Bool2ColorConverter BrushWhenFalse=Red, BrushWhenNull=Green, BrushWhenTrue=Blue}}"
            Content="Button" />
    </Grid>
</Window>

效果
在这里插入图片描述

CallExtension

将数据模型的函数与事件绑定起来

#region  << 版 本 注 释 >>
/*
 * ----------------------------------------------------------------
 * Copyright @ Daniel大妞 2021. All rights reserved.
 
 * 作    者 :Daniel大妞 (Daniel)
 
 * 创建时间 :2021/6/1 10:20:19
 
 * CLR 版本 :4.0.30319.42000
 
 * 命名空间 :DN.Controls.Markup
 
 * 类 名 称 :CallExtension

 * 类 描 述 :
 
 * ------------------------------------------------------
 * 历史更新记录
 
 * 版本 :  V1.0.0.0        修改时间:2021/6/1 10:20:19         修改人:Daniel大妞 (Daniel)
 
 * 修改内容:
 * 
 */
#endregion

using DN.Core;
using System;
using System.Reflection;
using System.Windows;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Markup;

namespace DN.Controls.Markup
{
    public class CallExtension : MarkupExtension
    {
        private readonly string m_MethodNameField;

        public CallExtension(string methodName)
        {
            this.m_MethodNameField = methodName;
        }

        /// <summary>
        /// 当在派生类中实现时,返回用作此标记扩展的目标属性值的对象。
        /// </summary>
        /// <param name="serviceProvider">可为标记扩展提供服务的服务提供程序帮助程序。</param>
        /// <returns>要在应用了扩展的属性上设置的对象值。</returns>
        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            IProvideValueTarget t = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget));
            return new CallCommand(t.TargetObject as FrameworkElement, this.m_MethodNameField);
        }

        internal class CallCommand : DependencyObject, ICommand
        {
            private static readonly Type MS_ThisType = typeof(CallCommand);
            private readonly FrameworkElement m_Element;
            private readonly string m_MethodName;
            private MethodInfo m_Method;

            public CallCommand(FrameworkElement element, string methodName)
            {
                if (element != null)
                {
                    this.m_Element = element;
                    this.m_MethodName = methodName;
                    element.DataContextChanged += this.OnDataContextChanged;
                    BindingOperations.SetBinding(this, CanCallProperty, new Binding("DataContext.Can" + methodName)
                    {
                        Source = element
                    });
                    this.GetMethod();
                }
            }

            #region ICommand

            public event EventHandler CanExecuteChanged;

            public bool CanExecute(object parameter)
            {
                return this.m_Method != null && this.CanCall;
            }

            public void Execute(object parameter)
            {
                this.m_Method.Invoke(this.DataContext, null);
            }
            #endregion

            /// <summary>
            /// 元素对象数据上下文
            /// </summary>
            public object DataContext => this.m_Element.DataContext;

            public bool CanCall
            {
                get => (bool)this.GetValue(CanCallProperty);
                set => this.SetValue(CanCallProperty, value);
            }

            public static readonly DependencyProperty CanCallProperty =
                DependencyProperty.Register(nameof(CanCall), typeof(bool), MS_ThisType, new PropertyMetadata(SharedInstances.BoxedTrue));

            protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
            {
                base.OnPropertyChanged(e);

                if (e.Property == CanCallProperty)
                {
                    this.RaiseCanExecuteChanged();
                }
            }

            private void GetMethod()
            {
                this.m_Method = this.DataContext?.GetType().GetMethod(this.m_MethodName, Type.EmptyTypes);
            }

            private void OnDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
            {
                this.GetMethod();
                this.RaiseCanExecuteChanged();
            }

            private void RaiseCanExecuteChanged()
            {
                this.CanExecuteChanged?.Invoke(this, EventArgs.Empty);
            }
        }
    }
}

示例:

<Window
    x:Class="wpf.CallExtensionTest.MainWindow"
    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:local="clr-namespace:wpf.CallExtensionTest"
    xmlns:markup="http://schemas.Daniel.com/DN.Controls"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Title="MainWindow"
    Width="800"
    Height="450"
    mc:Ignorable="d">
    <Grid>
        <Button Margin="85,29,448.6,278" Command="{markup:Call Run}" />
    </Grid>
</Window>
using System.Windows;

namespace wpf.CallExtensionTest
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = this;
        }

        public void Run()
        {
            ;
        }

        public bool CanRun => true;
    }
}

在这里插入图片描述

AssemblyTypeProviderExtension

#region  << 版 本 注 释 >>
/*
 * ----------------------------------------------------------------
 * Copyright @ Daniel大妞 2021. All rights reserved.
 
 * 作    者 :Daniel大妞 (Daniel)
 
 * 创建时间 :2021/6/15 22:22:12
 
 * CLR 版本 :4.0.30319.42000
 
 * 命名空间 :DN.Controls.Converters
 
 * 类 名 称 :AssemblyTypeProviderExtension

 * 类 描 述 :
 
 * ------------------------------------------------------
 * 历史更新记录
 
 * 版本 :  V1.0.0.0        修改时间:2021/6/15 22:22:12         修改人:Daniel大妞 (Daniel)
 
 * 修改内容:
 * 
 */
#endregion

using System;
using System.Globalization;
using System.Reflection;
using System.Windows.Data;
using System.Windows.Markup;

namespace DN.Controls.Converters
{
    public class AssemblyTypeProviderExtension: MarkupExtension, IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            string assemblyPath = value as string;
            if (string.IsNullOrWhiteSpace(assemblyPath) || !assemblyPath.EndsWith(".dll"))
            {
                return null;
            }
            else
            {
                try
                {
                    Assembly ass = Assembly.LoadFrom(assemblyPath);
                    return ass.GetExportedTypes();
                }
                catch
                {
                    return null;
                }
            }
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }

        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            return this;
        }
    }
}

示例:MainWindow.Xaml

<Window
    x:Class="wpf_AssemblyExtensionTest.MainWindow"
    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:local="clr-namespace:wpf_AssemblyExtensionTest"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    x:Name="PART_This"
    Title="MainWindow"
    Width="800"
    Height="450"
    mc:Ignorable="d">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="40" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <ListView Grid.Row="1" ItemsSource="{Binding ElementName=PART_This, Path=DllPath, UpdateSourceTrigger=PropertyChanged, Converter={local:AssemblyTypeProvider}}">
            <ListView.View>
                <GridView>
                    <GridView.Columns>
                        <GridViewColumn Header="FullName">
                            <GridViewColumn.CellTemplate>
                                <DataTemplate>
                                    <TextBlock Text="{Binding FullName}" />
                                </DataTemplate>
                            </GridViewColumn.CellTemplate>
                        </GridViewColumn>

                        <GridViewColumn Header="Fullss">
                            <GridViewColumn.CellTemplate>
                                <DataTemplate>
                                    <TextBlock Text="sdf" />
                                </DataTemplate>
                            </GridViewColumn.CellTemplate>
                        </GridViewColumn>
                    </GridView.Columns>
                </GridView>
            </ListView.View>
        </ListView>
        <Button
            x:Name="button"
            Width="75"
            Margin="16,10,0,0"
            HorizontalAlignment="Left"
            VerticalAlignment="Top"
            Click="button_Click"
            Content="Button" />
        <TextBox
            x:Name="listBox"
            Width="670"
            Height="35"
            Margin="105,0,0,0"
            HorizontalAlignment="Left"
            VerticalAlignment="Top"
            Text="{Binding ElementName=PART_This, Path=DllPath, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" />
    </Grid>

</Window>

示例:MainWindow.Xaml.cs

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;

namespace wpf_AssemblyExtensionTest
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        public string DllPath
        {
            get { return (string)GetValue(DllPathProperty); }
            set { SetValue(DllPathProperty, value); }
        }

        public static readonly DependencyProperty DllPathProperty =
            DependencyProperty.Register("DllPath", typeof(string), typeof(MainWindow));

        private void button_Click(object sender, RoutedEventArgs e)
        {
            Microsoft.Win32.OpenFileDialog openFileDialog = new Microsoft.Win32.OpenFileDialog
            {
                AddExtension = true,
                Filter = "All dll Files|*.dll;",
                Multiselect = false,
                CheckFileExists = true
            };
            if ((bool)openFileDialog.ShowDialog(Window.GetWindow(this)))
            {
                this.DllPath = openFileDialog.FileName;
            }
        }
    }
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Daniel大妞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值