WPF自定义控件 依赖属性绑定
Posted 风来风往风伤
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WPF自定义控件 依赖属性绑定相关的知识,希望对你有一定的参考价值。
控件cs文件
using System.ComponentModel; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Markup; using System.Windows.Media; namespace Controls { [TemplatePart(Name = "PART_DropDown", Type = typeof(System.Windows.Controls.Button))] [ContentProperty("Items")] [DefaultProperty("Items")] public class MyButton: System.Windows.Controls.Button { public static readonly DependencyProperty HorizontalOffsetProperty; public static readonly DependencyProperty IsContextMenuOpenProperty; public static readonly DependencyProperty ModeProperty; public static readonly DependencyProperty PlacementProperty; public static readonly DependencyProperty PlacementRectangleProperty; public static readonly DependencyProperty VerticalOffsetProperty; public static readonly DependencyProperty ImageSourceProperty = DependencyProperty.Register("ImageSource", typeof(string), typeof(MyButton), new PropertyMetadata("")); public static readonly DependencyProperty ImageSourceChangeProperty = DependencyProperty.Register("ImageSourceChange", typeof(string), typeof(MyButton), new PropertyMetadata("")); /// <summary> /// Static Constructor /// </summary> static MyButton() { DefaultStyleKeyProperty.OverrideMetadata(typeof(MyButton), new FrameworkPropertyMetadata(typeof(MyButton))); IsContextMenuOpenProperty = DependencyProperty.Register("IsContextMenuOpen", typeof(bool), typeof(MyButton), new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnIsContextMenuOpenChanged))); ModeProperty = DependencyProperty.Register("Mode", typeof(MyButtonMode), typeof(MyButton), new FrameworkPropertyMetadata(MyButtonMode.Split)); PlacementProperty = ContextMenuService.PlacementProperty.AddOwner(typeof(MyButton), new FrameworkPropertyMetadata(PlacementMode.Bottom, new PropertyChangedCallback(OnPlacementChanged))); PlacementRectangleProperty = ContextMenuService.PlacementRectangleProperty.AddOwner(typeof(MyButton), new FrameworkPropertyMetadata(Rect.Empty, new PropertyChangedCallback(OnPlacementRectangleChanged))); HorizontalOffsetProperty = ContextMenuService.HorizontalOffsetProperty.AddOwner(typeof(MyButton), new FrameworkPropertyMetadata(0.0, new PropertyChangedCallback(OnHorizontalOffsetChanged))); VerticalOffsetProperty = ContextMenuService.VerticalOffsetProperty.AddOwner(typeof(MyButton), new FrameworkPropertyMetadata(0.0, new PropertyChangedCallback(OnVerticalOffsetChanged))); } /* * Overrides * */ /// <summary> /// OnApplyTemplate override, set up the click event for the dropdown if present in the template /// </summary> public override void OnApplyTemplate() { base.OnApplyTemplate(); // set up the click event handler for the dropdown button System.Windows.Controls.Primitives.ButtonBase dropDown = this.Template.FindName("PART_DropDown", this) as System.Windows.Controls.Primitives.ButtonBase; if (dropDown != null) dropDown.Click += Dropdown_Click; } /// <summary> /// Handles the Base Buttons OnClick event /// </summary> protected override void OnClick() { switch (Mode) { case MyButtonMode.Dropdown: OnDropdown(); break; default: base.OnClick(); // forward on the Click event to the user break; } } /* * Properties * */ /// <summary> /// The Split Button‘s Items property maps to the base classes ContextMenu.Items property /// </summary> public ItemCollection Items { get { EnsureContextMenuIsValid(); return this.ContextMenu.Items; } } /* * DependencyProperty CLR wrappers * */ public string ImageSource { get { return (string)GetValue(ImageSourceProperty); } set { SetValue(ImageSourceProperty, value); } } public string ImageSourceChange { get { return (string)GetValue(ImageSourceChangeProperty); } set { SetValue(ImageSourceChangeProperty, value); } } /// <summary> /// Gets or sets the IsContextMenuOpen property. /// </summary> public bool IsContextMenuOpen { get { return (bool)GetValue(IsContextMenuOpenProperty); } set { SetValue(IsContextMenuOpenProperty, value); } } /// <summary> /// Placement of the Context menu /// </summary> public PlacementMode Placement { get { return (PlacementMode)GetValue(PlacementProperty); } set { SetValue(PlacementProperty, value); } } /// <summary> /// PlacementRectangle of the Context menu /// </summary> public Rect PlacementRectangle { get { return (Rect)GetValue(PlacementRectangleProperty); } set { SetValue(PlacementRectangleProperty, value); } } /// <summary> /// HorizontalOffset of the Context menu /// </summary> public double HorizontalOffset { get { return (double)GetValue(HorizontalOffsetProperty); } set { SetValue(HorizontalOffsetProperty, value); } } /// <summary> /// VerticalOffset of the Context menu /// </summary> public double VerticalOffset { get { return (double)GetValue(VerticalOffsetProperty); } set { SetValue(VerticalOffsetProperty, value); } } /// <summary> /// Defines the Mode of operation of the Button /// </summary> /// <remarks> /// The MyButton two Modes are /// Split (default), - the button has two parts, a normal button and a dropdown which exposes the ContextMenu /// Dropdown - the button acts like a combobox, clicking anywhere on the button opens the Context Menu /// </remarks> public MyButtonMode Mode { get { return (MyButtonMode)GetValue(ModeProperty); } set { SetValue(ModeProperty, value); } } /* * DependencyPropertyChanged callbacks * */ private static void OnIsContextMenuOpenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { MyButton s = (MyButton)d; s.EnsureContextMenuIsValid(); if (!s.ContextMenu.HasItems) return; bool value = (bool)e.NewValue; if (value && !s.ContextMenu.IsOpen) s.ContextMenu.IsOpen = true; else if (!value && s.ContextMenu.IsOpen) s.ContextMenu.IsOpen = false; } /// <summary> /// Placement Property changed callback, pass the value through to the buttons context menu /// </summary> private static void OnPlacementChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { MyButton s = d as MyButton; if (s == null) return; s.EnsureContextMenuIsValid(); s.ContextMenu.Placement = (PlacementMode)e.NewValue; } /// <summary> /// PlacementRectangle Property changed callback, pass the value through to the buttons context menu /// </summary> private static void OnPlacementRectangleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { MyButton s = d as MyButton; if (s == null) return; s.EnsureContextMenuIsValid(); s.ContextMenu.PlacementRectangle = (Rect)e.NewValue; } /// <summary> /// HorizontalOffset Property changed callback, pass the value through to the buttons context menu /// </summary> private static void OnHorizontalOffsetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { MyButton s = d as MyButton; if (s == null) return; s.EnsureContextMenuIsValid(); s.ContextMenu.HorizontalOffset = (double)e.NewValue; } /// <summary> /// VerticalOffset Property changed callback, pass the value through to the buttons context menu /// </summary> private static void OnVerticalOffsetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { MyButton s = d as MyButton; if (s == null) return; s.EnsureContextMenuIsValid(); s.ContextMenu.VerticalOffset = (double)e.NewValue; } /* * Helper Methods * */ /// <summary> /// Make sure the Context menu is not null /// </summary> private void EnsureContextMenuIsValid() { if (this.ContextMenu == null) { this.ContextMenu = new System.Windows.Controls.ContextMenu(); this.ContextMenu.PlacementTarget = this; this.ContextMenu.Placement = Placement; this.ContextMenu.Opened += ((sender, routedEventArgs) => IsContextMenuOpen = true); this.ContextMenu.Closed += ((sender, routedEventArgs) => IsContextMenuOpen = false); } } private void OnDropdown() { EnsureContextMenuIsValid(); if (!this.ContextMenu.HasItems) return; this.ContextMenu.IsOpen = !IsContextMenuOpen; // open it if closed, close it if open } /* * Events * */ /// <summary> /// Event Handler for the Drop Down Button‘s Click event /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Dropdown_Click(object sender, RoutedEventArgs e) { OnDropdown(); e.Handled = true; } } }
控件xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:comm="clr-namespace:Controls"> <Style x:Key="ButtonFocusVisual"> <Setter Property="Control.Template"> <Setter.Value> <ControlTemplate> <Rectangle Margin="3" SnapsToDevicePixels="true" Stroke="Transparent" StrokeDashArray="1 2" StrokeThickness="1" /> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style TargetType="Button"> <Setter Property="Foreground" Value="#D5D5D5" /> <Setter Property="FontSize" Value="13" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="Button"> <Image x:Name="image" HorizontalAlignment="Center" VerticalAlignment="Center" Source="{Binding Path=ImageSource, RelativeSource={RelativeSource AncestorType={x:Type comm:MyButton}}}" /> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter TargetName="image" Property="Source" Value="{Binding Path=ImageSourceChange, RelativeSource={RelativeSource AncestorType={x:Type comm:MyButton}}}" /> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style TargetType="{x:Type comm:MyButton}"> <Setter Property="FocusVisualStyle" Value="{StaticResource ButtonFocusVisual}" /> <Setter Property="FontSize" Value="13" /> <Setter Property="Foreground" Value="#D5D5D5" /> <Setter Property="FontFamily" Value="微软雅黑" /> <Setter Property="HorizontalContentAlignment" Value="Center" /> <Setter Property="VerticalContentAlignment" Value="Center" /> <Setter Property="Padding" Value="0" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type comm:MyButton}"> <Border x:Name="grid" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="Transparent" CornerRadius="4"> <Button x:Name="PART_DropDown" /> </Border> <ControlTemplate.Triggers> <Trigger SourceName="PART_DropDown" Property="IsMouseOver" Value="true"> <Setter TargetName="PART_DropDown" Property="Opacity" Value="1" /> <Setter TargetName="grid" Property="Background" Value="Transparent" /> </Trigger> <Trigger Property="IsEnabled" Value="false"> <Setter Property="Foreground" Value="#ADADAD" /> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> </ResourceDictionary>
页面使用:
<comm:MyButton Width="38" Height="40" ImageSource="/control;component/Icons/picture2.png" ImageSourceChange="/control;component/Icons/picture1.png"> </comm:MyButton>
以上是关于WPF自定义控件 依赖属性绑定的主要内容,如果未能解决你的问题,请参考以下文章