您好,欢迎来到飒榕旅游知识分享网。
搜索
您的当前位置:首页wpf 无外观控件通过重写OnApplyTemplate进行代码绑定,减少模板绑定代码

wpf 无外观控件通过重写OnApplyTemplate进行代码绑定,减少模板绑定代码

来源:飒榕旅游知识分享网

1 新建wpf项目

2 新建wpf UserControl类库

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.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;

namespace CustomControl
{
    [TemplatePart(Name = "PART_RedSlider", Type = typeof(RangeBase))]
    [TemplatePart(Name = "PART_BlueSlider", Type = typeof(RangeBase))]
    [TemplatePart(Name = "PART_GreenSlider", Type = typeof(RangeBase))]
    [TemplatePart(Name = "PART_PreviewBrush", Type = typeof(SolidColorBrush))]
    public class ColorPicker : Control
    {
        public Color Color
        {
            get { return (Color)GetValue(ColorProperty); }
            set { SetValue(ColorProperty, value); }
        }

        public byte Red
        {
            get { return (byte)GetValue(RedProperty); }
            set { SetValue(RedProperty, value); }
        }
        public byte Green
        {
            get { return (byte)GetValue(GreenProperty); }
            set { SetValue(GreenProperty, value); }
        }

        public byte Blue
        {
            get { return (byte)GetValue(BlueProperty); }
            set { SetValue(BlueProperty, value); }
        }

        public static readonly DependencyProperty ColorProperty =
            DependencyProperty.Register("Color", typeof(Color), typeof(ColorPicker), new PropertyMetadata(Colors.Black, OnColorChanged));

        public static readonly DependencyProperty RedProperty =
            DependencyProperty.Register("Red", typeof(byte), typeof(ColorPicker), new PropertyMetadata(OnColorRGBChanged));

        public static readonly DependencyProperty GreenProperty =
            DependencyProperty.Register("Green", typeof(byte), typeof(ColorPicker), new PropertyMetadata(OnColorRGBChanged));

        public static readonly DependencyProperty BlueProperty =
            DependencyProperty.Register("Blue", typeof(byte), typeof(ColorPicker), new PropertyMetadata(OnColorRGBChanged));

        private static void OnColorRGBChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ColorPicker uc = (ColorPicker)d;
            Color color = uc.Color;
            if (e.Property == RedProperty)
            {
                color.R = (byte)e.NewValue;
            }
            else if (e.Property == GreenProperty)
            {
                color.G = (byte)e.NewValue;
            }
            else if (e.Property == BlueProperty)
            {
                color.B = (byte)e.NewValue;
            }
            uc.Color = color;
        }

        private static void OnColorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ColorPicker uc = (ColorPicker)d;
            Color color = (Color)e.NewValue;
            uc.Red = color.R;
            uc.Green = color.G;
            uc.Blue = color.B;

            Color oldColor = (Color)e.OldValue;
            uc.PreviousColor = oldColor;

            RoutedPropertyChangedEventArgs<Color> args = new RoutedPropertyChangedEventArgs<Color>(oldColor, color);
            args.RoutedEvent = ColorChangedEvent;
            uc.RaiseEvent(args);

        }


        public static readonly RoutedEvent ColorChangedEvent = EventManager.RegisterRoutedEvent("ColorChanged", RoutingStrategy.Bubble,
            typeof(RoutedPropertyChangedEventHandler<Color>), typeof(ColorPickerUserControl));

        public event RoutedPropertyChangedEventHandler<Color> ColorChanged
        {
            add { AddHandler(ColorChangedEvent, value); }
            remove { RemoveHandler(ColorChangedEvent, value); }
        }


        Color? PreviousColor;


        public ColorPicker()
        {
            CommandBinding binding = new CommandBinding(ApplicationCommands.Undo,
              UndoCommand_Executed, UndoCommand_CanExecute);

            this.CommandBindings.Add(binding);
        }

        private void UndoCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = PreviousColor.HasValue;
        }

        private void UndoCommand_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            this.Color = (Color)PreviousColor;
        }

        static ColorPicker()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(ColorPicker), new FrameworkPropertyMetadata(typeof(ColorPicker)));
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            RangeBase slider = GetTemplateChild("PART_RedSlider") as RangeBase;
            if (slider != null)
            {
                Binding binding = new Binding("Red");
                binding.Source = this;
                binding.Mode = BindingMode.TwoWay;
                slider.SetBinding(RangeBase.ValueProperty, binding);
            }
            slider = GetTemplateChild("PART_GreenSlider") as RangeBase;
            if (slider != null)
            {
                Binding binding = new Binding("Green");
                binding.Source = this;
                binding.Mode = BindingMode.TwoWay;
                slider.SetBinding(RangeBase.ValueProperty, binding);
            }
            slider = GetTemplateChild("PART_BlueSlider") as RangeBase;
            if (slider != null)
            {
                Binding binding = new Binding("Blue");
                binding.Source = this;
                binding.Mode = BindingMode.TwoWay;
                slider.SetBinding(RangeBase.ValueProperty, binding);
            }

            SolidColorBrush brush = GetTemplateChild("PART_PreviewBrush") as SolidColorBrush;
            if (brush != null)
            {
                Binding binding = new Binding("Color");
                binding.Source = brush;
                binding.Mode = BindingMode.OneWayToSource;
                this.SetBinding(ColorPicker.ColorProperty, binding);
            }
        }
    }
}

3 新建Themes文件夹,新建generic.xaml资源字典

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:CustomControl.Themes">
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="/CustomControl;component/Themes/ColorPicker.xaml" />
    </ResourceDictionary.MergedDictionaries>
    
</ResourceDictionary>

新建ColorPicker.xaml资源字典,注意在这里给每个Slider和SolidColorBrush都命名,并将其Value,Color属性绑定删掉,从而在代码中绑定

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:CustomControl">
    <Style TargetType="{x:Type local:ColorPicker}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:ColorPicker}">
                    <Border Background="{TemplateBinding Background}"
                  BorderBrush="{TemplateBinding BorderBrush}"
                  BorderThickness="{TemplateBinding BorderThickness}">
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto"></RowDefinition>
                                <RowDefinition Height="Auto"></RowDefinition>
                                <RowDefinition Height="Auto"></RowDefinition>
                            </Grid.RowDefinitions>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition></ColumnDefinition>
                                <ColumnDefinition Width="Auto"></ColumnDefinition>
                            </Grid.ColumnDefinitions>

                            <Slider Name="PART_RedSlider" Minimum="0" Maximum="255" 
                       Margin="{TemplateBinding Padding}"></Slider>
                            <Slider Grid.Row="1" Name="PART_GreenSlider" Minimum="0" Maximum="255"
                       Margin="{TemplateBinding Padding}"></Slider>

                            <Slider Grid.Row="2" Name="PART_BlueSlider" Minimum="0" Maximum="255"
                       Margin="{TemplateBinding Padding}"></Slider>

                            <Rectangle Grid.Column="1" Grid.RowSpan="3"
                         Margin="{TemplateBinding Padding}"
                         Width="50" Stroke="Black" StrokeThickness="1">
                                <Rectangle.Fill>
                                    <SolidColorBrush x:Name="PART_PreviewBrush"></SolidColorBrush>
                                </Rectangle.Fill>
                            </Rectangle>

                        </Grid>

                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

</ResourceDictionary>

4 主程序中,有两个控件引用,一个使用默认模板,一个使用新的模板,因为数据绑定已经在代码中实现,所以,所有的模板只要关注布局就可以了

<Window x:Class="CustomControlApp.ColorPickerTwoWays"
        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"
        xmlns:local="clr-namespace:CustomControlApp"
        xmlns:lib="clr-namespace:CustomControl;assembly=CustomControl"
        mc:Ignorable="d"
        Title="ColorPickerTwoWays" Height="450" Width="800">
    <Window.Resources>
        <ControlTemplate x:Key="FancyColorPickerTemplate">
            <Border Background="LightGoldenrodYellow"
                BorderBrush="Black"
                BorderThickness="1">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition></RowDefinition>
                        <RowDefinition Height="Auto"></RowDefinition>
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition></ColumnDefinition>
                        <ColumnDefinition Width="Auto"></ColumnDefinition>
                        <ColumnDefinition Width="Auto"></ColumnDefinition>
                        <ColumnDefinition Width="Auto"></ColumnDefinition>
                    </Grid.ColumnDefinitions>

                    <Grid.Resources>
                        <Style TargetType="{x:Type Slider}">
                            <Setter Property="Orientation" Value="Vertical"></Setter>
                            <Setter Property="TickPlacement" Value="TopLeft"></Setter>
                            <Setter Property="TickFrequency" Value="10"></Setter>
                            <Setter Property="Minimum" Value="0"></Setter>
                            <Setter Property="Maximum" Value="255"></Setter>
                            <Setter Property="Margin" Value="5"></Setter>
                        </Style>
                        <Style TargetType="{x:Type TextBlock}">
                            <Setter Property="Margin" Value="3"></Setter>
                            <Setter Property="FontSize" Value="10"></Setter>
                        </Style>
                    </Grid.Resources>

                    <Ellipse Grid.Column="0" Grid.RowSpan="2" 
                       Margin="10" Height="120" Stroke="LightGray" StrokeThickness="5">
                        <Ellipse.Fill>
                            <SolidColorBrush Color="{Binding Path=Color,
                       RelativeSource={RelativeSource TemplatedParent}}"></SolidColorBrush>
                        </Ellipse.Fill>
                    </Ellipse>


                    <Slider Name="PART_RedSlider" Grid.Column="1"></Slider>
                    <TextBlock Grid.Row="1" Grid.Column="1">RED</TextBlock>
                    <Slider Name="PART_GreenSlider" Grid.Column="2"></Slider>
                    <TextBlock Grid.Row="1" Grid.Column="2">GREEN</TextBlock>
                    <Slider Name="PART_BlueSlider" Grid.Column="3"></Slider>
                    <TextBlock Grid.Row="1" Grid.Column="3">BLUE</TextBlock>


                </Grid>

            </Border>
        </ControlTemplate>

    </Window.Resources>
    <StackPanel>
        <lib:ColorPicker
      Name="colorPicker1" Margin="2" Padding="3" Color="AliceBlue"></lib:ColorPicker>
        <lib:ColorPicker 
      Name="colorPicker2" Template="{StaticResource FancyColorPickerTemplate}" Color="{Binding ElementName=colorPicker1,Path=Color,Mode=TwoWay}"
      Margin="5,20,5,5" ></lib:ColorPicker>

    </StackPanel>
</Window>

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- sarr.cn 版权所有 赣ICP备2024042794号-1

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务