当前位置:网站首页 / WPF / 正文

2020 WPF 取经之路第7天- ControlzEx,MahApps最新的core3代码 部分迁移换4.0

时间:2020年04月14日 | 作者 : aaronyang | 分类 : WPF | 浏览: 84次 | 评论 0


这次要提取metrowindow的东西

下载:https://github.com/MahApps/MahApps.Metro/tree/dev-net40


新建wpf自定义控件库,引用

image.png

这个

ReSharper注释有助于减少误报,在代码中明确声明纯净性和可空性,处理成员的隐式用法,在ASP.NET和XAML框架中支持API的特殊语义,以及提高ReSharper代码检查的准确性。

主要就是共用的特性,语义化代码


接下来下载https://github.com/ControlzEx/ControlzEx源码

看下面报告,好东西学下

看到个野性写法,也不知道为啥要这么弄

   internal static class TabItemExtensions
    {
        private static readonly MethodInfo SetFocusMethodInfo = typeof(TabItem).GetMethod("SetFocus", BindingFlags.NonPublic | BindingFlags.Instance);

        internal static bool SetFocus(this TabItem tabItem)
        {
            return (bool)SetFocusMethodInfo.Invoke(tabItem, null);
        }
    }


下载的代码是4.5以上的,我去掉tabcontrol,掩码和主题功能,改成了4.0

迁移完后,试下demo

image.png


xmlns:controlzex="urn:controlzex" 


DEMO1 显示FocusVisualStyle  controlzex:KeyboardNavigationEx.AlwaysShowFocusVisual="True"

    <Grid>
        <StackPanel>
            <Button controlzex:KeyboardNavigationEx.AlwaysShowFocusVisual="True" Width="120" Height="40">显示FocusVisual</Button>
            <Button controlzex:KeyboardNavigationEx.AlwaysShowFocusVisual="True" Width="120" Height="40">显示FocusVisual</Button>
            <Button controlzex:KeyboardNavigationEx.AlwaysShowFocusVisual="True" Width="120" Height="40">显示FocusVisual</Button>
            <Button Width="120" Height="40" x:Name="btn1">不显示FocusVisual</Button>
            <Button Width="120" Height="40" Click="Button_Click_1">单击我,上一个按钮被显示</Button>
            <Button Width="120" Height="40">不显示FocusVisual</Button>
            <Button Width="120" Height="40">不显示FocusVisual</Button>
        </StackPanel>
    </Grid>

后台

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            KeyboardNavigationEx.Focus(this.btn1);
        }

感觉如果这个功能要是有用的话,也就是 后台新手导航,没啥用。



DEMO2 提示跟着鼠标走  controlzex:ToolTipAssist.AutoMove="True"

  <Button Width="120" Height="40"  Margin="5" Padding="5" Content="移动到按钮上,提示跟着走" ToolTipService.ShowDuration="20000">
            <Button.ToolTip>
                <ToolTip controlzex:ToolTipAssist.AutoMove="True">
                    <ToolTip.Template>
                        <ControlTemplate>
                            <Grid>
                                <Border Background="Gray" BorderBrush="Black" BorderThickness="1" Opacity="0.9" SnapsToDevicePixels="True" />
                                <TextBlock Margin="5" Foreground="WhiteSmoke" FontSize="22" Text="Tooltip跟着走" TextOptions.TextFormattingMode="Display" TextOptions.TextRenderingMode="ClearType" />
                            </Grid>
                        </ControlTemplate>
                    </ToolTip.Template>
                </ToolTip>
            </Button.ToolTip>
        </Button>

image.png




ControlzEx为WPF窗口提供了自定义镶边,并为其提供了其他一些更深入的修复。

大多数修复和改进来自MahApps.Metro和Fluent.Ribbon。

这里描述的技术的具体实现:

http://blogs.msdn.com/b/wpfsdk/archive/2008/09/08/custom-window-chrome-in-wpf.aspx

它是原始Microsoft WPF Shell集成库的分支。 当前Microsoft的实现可以找到:

https://github.com/dotnet/wpf

http://referencesource.microsoft.com


DEMO3 很常用,popupex

 <controlzex:PopupEx IsOpen="True" AllowsTransparency="True" Placement="Right" CloseOnMouseLeftButtonDown="True" PlacementTarget="{Binding ElementName=te}">
            <Border Width="400" Height="400" Background="White" BorderBrush="Blue" BorderThickness="2">
                <TextBlock Text="AY测试弹窗" />
            </Border>
        </controlzex:PopupEx>

真的好东西,解决了,

CloseOnMouseLeftButtonDown 左键单击关闭,

跟着窗体,绑定的target 移动,窗体隐藏就隐藏,还可以不置顶其他元素,如果wpf自带的popup绝对不行的,他永远置顶于任何东西。

image.png

我添加了我的WpfTreeHelper类

自己写了个ThumbControlMovePopupBehavior行为类

using System.Windows;
using System.Windows.Controls.Primitives;
using System.Windows.Interactivity;

namespace ControlzEx
{
    public class ThumbControlMovePopupBehavior : Behavior<Thumb>
    {

        public ThumbControlMovePopupBehavior()
        {

        }


        public Popup TargetPopup
        {
            get { return (Popup)GetValue(TargetPopupProperty); }
            set { SetValue(TargetPopupProperty, value); }
        }
        public static readonly DependencyProperty TargetPopupProperty =
            DependencyProperty.Register("TargetPopup", typeof(Popup), typeof(ThumbControlMovePopupBehavior), new PropertyMetadata(null));


        protected override void OnAttached()
        {
            base.OnAttached();
           AssociatedObject.DragDelta += AssociatedObject_DragDelta;
        }

        private void AssociatedObject_DragDelta(object sender, DragDeltaEventArgs e)
        {
            if (TargetPopup == null) return;
            TargetPopup.HorizontalOffset += e.HorizontalChange;
            TargetPopup.VerticalOffset += e.VerticalChange;
        }

        protected override void OnDetaching()
        {
            base.OnDetaching();
            AssociatedObject.DragDelta -= AssociatedObject_DragDelta;
        }



    }
}
  <controlzex:PopupEx IsOpen="True" AllowsTransparency="True" Placement="Right" PlacementTarget="{Binding ElementName=te}">
            <Border Width="400" Height="400" Background="White" BorderBrush="Blue" BorderThickness="2">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="30"/>
                        <RowDefinition Height="*"/>
                    </Grid.RowDefinitions>

                <Thumb Width="20" Height="20" Background="Green">
                    <i:Interaction.Behaviors>
                            <controlzex:ThumbControlMovePopupBehavior TargetPopup="{Binding .,RelativeSource={RelativeSource AncestorType={x:Type controlzex:PopupEx},Mode=FindAncestor}}"/>
                    </i:Interaction.Behaviors>
                </Thumb>
                <TextBlock Grid.Row="1" Text="AY测试弹窗" />
                </Grid>
            </Border>
        </controlzex:PopupEx>

效果

1212.gif

这个项目多 MaterialDesignInXamlToolkit or MahApps.Metro.



DEMO4 BadgedEx,源码没有提供样式文件

在MahApps源码,迁移Badged.cs 拓展了动画模板

  [TemplatePart(Name = BadgeContainerPartName, Type = typeof(UIElement))]
    public class Badged : BadgedEx
    {
        public static readonly DependencyProperty BadgeChangedStoryboardProperty = DependencyProperty.Register(
            "BadgeChangedStoryboard", typeof(Storyboard), typeof(Badged), new PropertyMetadata(default(Storyboard)));

        public Storyboard BadgeChangedStoryboard
        {
            get { return (Storyboard)this.GetValue(BadgeChangedStoryboardProperty); }
            set { this.SetValue(BadgeChangedStoryboardProperty, value); }
        }

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

        public override void OnApplyTemplate()
        {
            this.BadgeChanged -= this.OnBadgeChanged;

            base.OnApplyTemplate();

            this.BadgeChanged += this.OnBadgeChanged;
        }

        private void OnBadgeChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
        {
            var sb = this.BadgeChangedStoryboard;
            if (this._badgeContainer != null && sb != null)
            {
                try
                {
                    this._badgeContainer.BeginStoryboard(sb);
                }
                catch (Exception exception)
                {
                    throw new AyxAppsException("Uups, it seems like there is something wrong with the given Storyboard.", exception);
                }
            }
        }

样式文件

    <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
    <SineEase x:Key="BadgeEase" EasingMode="EaseOut" />
    <Storyboard x:Key="BadgeChangedStoryboard">
        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleX)">
            <EasingDoubleKeyFrame KeyTime="0" Value="1.4" />
            <EasingDoubleKeyFrame EasingFunction="{StaticResource BadgeEase}" KeyTime="0:0:0.3" Value="1" />
        </DoubleAnimationUsingKeyFrames>
        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)">
            <EasingDoubleKeyFrame KeyTime="0" Value="1.4" />
            <EasingDoubleKeyFrame EasingFunction="{StaticResource BadgeEase}" KeyTime="0:0:0.3" Value="1" />
        </DoubleAnimationUsingKeyFrames>
    </Storyboard>


    <Style TargetType="{x:Type controlzex:Badged}">
        <Setter Property="BadgeBackground" Value="Red" />
        <Setter Property="BadgeChangedStoryboard" Value="{StaticResource BadgeChangedStoryboard}" />
        <Setter Property="BadgeForeground" Value="#FFFFFF" />
        <Setter Property="BadgePlacementMode" Value="TopRight" />
        <Setter Property="HorizontalContentAlignment" Value="Stretch" />
        <Setter Property="IsTabStop" Value="False" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type controlzex:Badged}">
                    <Grid>
                        <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
                            <ContentPresenter Margin="{TemplateBinding Padding}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" ContentTemplate="{TemplateBinding ContentTemplate}" ContentTemplateSelector="{TemplateBinding ContentTemplateSelector}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                        </Border>
                        <Border x:Name="PART_BadgeContainer" MinWidth="18" MinHeight="18" Padding="2" HorizontalAlignment="Left" VerticalAlignment="Top" Background="{TemplateBinding BadgeBackground}" CornerRadius="9" RenderTransformOrigin=".5,.5" TextElement.FontSize="11" TextElement.FontWeight="DemiBold" Visibility="{TemplateBinding IsBadgeSet, Converter={StaticResource BooleanToVisibilityConverter}}">
                            <Border.RenderTransform>
                                <ScaleTransform ScaleX="1" ScaleY="1" />
                            </Border.RenderTransform>
                            <ContentControl Margin="1 0 1 0" HorizontalAlignment="Center" VerticalAlignment="Center" Content="{TemplateBinding Badge}" Focusable="False" Foreground="{TemplateBinding BadgeForeground}" IsTabStop="False" />
                        </Border>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="BadgePlacementMode" Value="TopLeft">
                            <Setter TargetName="PART_BadgeContainer" Property="HorizontalAlignment" Value="Left" />
                            <Setter TargetName="PART_BadgeContainer" Property="VerticalAlignment" Value="Top" />
                        </Trigger>
                        <Trigger Property="BadgePlacementMode" Value="Top">
                            <Setter TargetName="PART_BadgeContainer" Property="HorizontalAlignment" Value="Center" />
                            <Setter TargetName="PART_BadgeContainer" Property="VerticalAlignment" Value="Top" />
                        </Trigger>
                        <Trigger Property="BadgePlacementMode" Value="TopRight">
                            <Setter TargetName="PART_BadgeContainer" Property="HorizontalAlignment" Value="Right" />
                            <Setter TargetName="PART_BadgeContainer" Property="VerticalAlignment" Value="Top" />
                        </Trigger>
                        <Trigger Property="BadgePlacementMode" Value="Right">
                            <Setter TargetName="PART_BadgeContainer" Property="HorizontalAlignment" Value="Right" />
                            <Setter TargetName="PART_BadgeContainer" Property="VerticalAlignment" Value="Center" />
                        </Trigger>
                        <Trigger Property="BadgePlacementMode" Value="BottomRight">
                            <Setter TargetName="PART_BadgeContainer" Property="HorizontalAlignment" Value="Right" />
                            <Setter TargetName="PART_BadgeContainer" Property="VerticalAlignment" Value="Bottom" />
                        </Trigger>
                        <Trigger Property="BadgePlacementMode" Value="Bottom">
                            <Setter TargetName="PART_BadgeContainer" Property="HorizontalAlignment" Value="Center" />
                            <Setter TargetName="PART_BadgeContainer" Property="VerticalAlignment" Value="Bottom" />
                        </Trigger>
                        <Trigger Property="BadgePlacementMode" Value="BottomLeft">
                            <Setter TargetName="PART_BadgeContainer" Property="HorizontalAlignment" Value="Left" />
                            <Setter TargetName="PART_BadgeContainer" Property="VerticalAlignment" Value="Bottom" />
                        </Trigger>
                        <Trigger Property="BadgePlacementMode" Value="Left">
                            <Setter TargetName="PART_BadgeContainer" Property="HorizontalAlignment" Value="Left" />
                            <Setter TargetName="PART_BadgeContainer" Property="VerticalAlignment" Value="Center" />
                        </Trigger>
                        <Trigger Property="IsEnabled" Value="False">
                            <Setter TargetName="PART_BadgeContainer" Property="Background" Value="#FF666666" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Setter Property="VerticalContentAlignment" Value="Stretch" />
    </Style>


xaml demo用法 Badged

<StackPanel x:Name="dasf">
            <Label Content="按钮"  />
            <controlzex:Badged Width="120"   Badge="123" >
                <Button Content="角徽显示123"  Width="auto" Height="40"/>
            </controlzex:Badged>
            <controlzex:Badged Margin="0,10,0,0" Width="180" BadgePlacementMode="TopLeft" Badge="2" IsEnabled="False">
                <Button Content="禁用时候角徽,显示在下面" Height="40"/>
            </controlzex:Badged>
            <controlzex:Badged Margin="0,10,0,0"  Width="130"  Badge="" >
                <Button Content="值为空白不显示角徽" Height="40" />
            </controlzex:Badged>

            <Button Width="100" Margin="0,10,0,0"  Content="普通按钮" />
            <Button Width="100" Margin="0,10,0,0" Content="普通按钮禁用" IsEnabled="False" />
        </StackPanel>

效果图

image.png

DEMO5 窗体,迁移MahApps的

迁移MetroWindow,TreeHelper等文件修改

TreeHelper这个源码很有价值,有对我的WpfTreeHelper的补充

源码如下,可以直接拿走

using System.Collections.Generic;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Media3D;

namespace ControlzEx
{
    /// <summary>
    /// Helper methods for UI-related tasks.
    /// This class was obtained from Philip Sumi (a fellow WPF Disciples blog)
    /// http://www.hardcodet.net/uploads/2009/06/UIHelper.cs
    /// </summary>
    public static class TreeHelper
    {
        /// <summary>
        /// Finds a parent of a given item on the visual tree.
        /// </summary>
        /// <typeparam name="T">The type of the queried item.</typeparam>
        /// <param name="child">A direct or indirect child of the
        /// queried item.</param>
        /// <returns>The first parent item that matches the submitted
        /// type parameter. If not matching item can be found, a null
        /// reference is being returned.</returns>
        public static T TryFindParent<T>(this DependencyObject child)
            where T : DependencyObject
        {
            //get parent item
            DependencyObject parentObject = GetParentObject(child);

            //we've reached the end of the tree
            if (parentObject == null) return null;

            //check if the parent matches the type we're looking for
            T parent = parentObject as T;
            return parent ?? TryFindParent<T>(parentObject);
        }

        /// <summary>
        /// Finds all Ancestors of a given item on the visual tree.
        /// </summary>
        /// <param name="child">A node in a visual tree</param>
        /// <returns>All ancestors in visual tree of <paramref name="child"/> element</returns>
        public static IEnumerable<DependencyObject> GetAncestors(this DependencyObject child)
        {
            var parent = VisualTreeHelper.GetParent(child);
            while (parent != null)
            {
                yield return parent;
                parent = VisualTreeHelper.GetParent(parent);
            }
        }

        /// <summary>
        /// Finds a Child of a given item in the visual tree. 
        /// </summary>
        /// <param name="parent">A direct parent of the queried item.</param>
        /// <typeparam name="T">The type of the queried item.</typeparam>
        /// <param name="childName">x:Name or Name of child. </param>
        /// <returns>The first parent item that matches the submitted type parameter. 
        /// If not matching item can be found, 
        /// a null parent is being returned.</returns>
        public static T FindChild<T>(this DependencyObject parent, string childName)
           where T : DependencyObject
        {
            // Confirm parent and childName are valid. 
            if (parent == null) return null;

            T foundChild = null;

            int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
            for (int i = 0; i < childrenCount; i++)
            {
                var child = VisualTreeHelper.GetChild(parent, i);
                // If the child is not of the request child type child
                T childType = child as T;
                if (childType == null)
                {
                    // recursively drill down the tree
                    foundChild = FindChild<T>(child, childName);
                    // If the child is found, break so we do not overwrite the found child. 
                    if (foundChild != null) break;
                }
                else if (!string.IsNullOrEmpty(childName))
                {
                    var frameworkInputElement = child as IFrameworkInputElement;
                    // If the child's name is set for search
                    if (frameworkInputElement != null && frameworkInputElement.Name == childName)
                    {
                        // if the child's name is of the request name
                        foundChild = (T)child;
                        break;
                    }
                    else
                    {
                        // recursively drill down the tree
                        foundChild = FindChild<T>(child, childName);
                        // If the child is found, break so we do not overwrite the found child. 
                        if (foundChild != null) break;
                    }
                }
                else
                {
                    // child element found.
                    foundChild = (T)child;
                    break;
                }
            }

            return foundChild;
        }

        /// <summary>
        /// This method is an alternative to WPF's
        /// <see cref="VisualTreeHelper.GetParent"/> method, which also
        /// supports content elements. Keep in mind that for content element,
        /// this method falls back to the logical tree of the element!
        /// </summary>
        /// <param name="child">The item to be processed.</param>
        /// <returns>The submitted item's parent, if available. Otherwise
        /// null.</returns>
        public static DependencyObject GetParentObject(this DependencyObject child)
        {
            if (child == null) return null;

            // handle content elements separately
            var contentElement = child as ContentElement;
            if (contentElement != null)
            {
                DependencyObject parent = ContentOperations.GetParent(contentElement);
                if (parent != null) return parent;

                var fce = contentElement as FrameworkContentElement;
                return fce != null ? fce.Parent : null;
            }

            var childParent = VisualTreeHelper.GetParent(child);
            if (childParent != null)
            {
                return childParent;
            }

            // also try searching for parent in framework elements (such as DockPanel, etc)
            var frameworkElement = child as FrameworkElement;
            if (frameworkElement != null)
            {
                DependencyObject parent = frameworkElement.Parent;
                if (parent != null) return parent;
            }

            return null;
        }

        /// <summary>
        /// Analyzes both visual and logical tree in order to find all elements of a given
        /// type that are descendants of the <paramref name="source"/> item.
        /// </summary>
        /// <typeparam name="T">The type of the queried items.</typeparam>
        /// <param name="source">The root element that marks the source of the search. If the
        /// source is already of the requested type, it will not be included in the result.</param>
        /// <param name="forceUsingTheVisualTreeHelper">Sometimes it's better to search in the VisualTree (e.g. in tests)</param>
        /// <returns>All descendants of <paramref name="source"/> that match the requested type.</returns>
        public static IEnumerable<T> FindChildren<T>(this DependencyObject source, bool forceUsingTheVisualTreeHelper = false) where T : DependencyObject
        {
            if (source != null)
            {
                var childs = GetChildObjects(source, forceUsingTheVisualTreeHelper);
                foreach (DependencyObject child in childs)
                {
                    //analyze if children match the requested type
                    if (child != null && child is T)
                    {
                        yield return (T)child;
                    }

                    //recurse tree
                    foreach (T descendant in FindChildren<T>(child, forceUsingTheVisualTreeHelper))
                    {
                        yield return descendant;
                    }
                }
            }
        }

        /// <summary>
        /// This method is an alternative to WPF's
        /// <see cref="VisualTreeHelper.GetChild"/> method, which also
        /// supports content elements. Keep in mind that for content elements,
        /// this method falls back to the logical tree of the element.
        /// </summary>
        /// <param name="parent">The item to be processed.</param>
        /// <param name="forceUsingTheVisualTreeHelper">Sometimes it's better to search in the VisualTree (e.g. in tests)</param>
        /// <returns>The submitted item's child elements, if available.</returns>
        public static IEnumerable<DependencyObject> GetChildObjects(this DependencyObject parent, bool forceUsingTheVisualTreeHelper = false)
        {
            if (parent == null) yield break;

            if (!forceUsingTheVisualTreeHelper && (parent is ContentElement || parent is FrameworkElement))
            {
                //use the logical tree for content / framework elements
                foreach (object obj in LogicalTreeHelper.GetChildren(parent))
                {
                    var depObj = obj as DependencyObject;
                    if (depObj != null) yield return (DependencyObject)obj;
                }
            }
            else if (parent is Visual || parent is Visual3D)
            {
                //use the visual tree per default
                int count = VisualTreeHelper.GetChildrenCount(parent);
                for (int i = 0; i < count; i++)
                {
                    yield return VisualTreeHelper.GetChild(parent, i);
                }
            }
        }

        /// <summary>
        /// Tries to locate a given item within the visual tree,
        /// starting with the dependency object at a given position. 
        /// </summary>
        /// <typeparam name="T">The type of the element to be found
        /// on the visual tree of the element at the given location.</typeparam>
        /// <param name="reference">The main element which is used to perform
        /// hit testing.</param>
        /// <param name="point">The position to be evaluated on the origin.</param>
        public static T TryFindFromPoint<T>(UIElement reference, Point point)
            where T : DependencyObject
        {
            var element = reference.InputHitTest(point) as DependencyObject;

            if (element == null)
                return null;
            if (element is T)
                return (T)element;
            return TryFindParent<T>(element);
        }
    }
}

MahApp加了ContentControlEx.cs

public class ContentControlEx : ContentControl
    {
        /// <summary>
        /// The DependencyProperty for the CharacterCasing property.
        /// Controls whether or not content is converted to upper or lower case
        /// Default Value: CharacterCasing.Normal
        /// </summary>
        public static readonly DependencyProperty ContentCharacterCasingProperty =
            DependencyProperty.Register("ContentCharacterCasing",
                                        typeof(CharacterCasing),
                                        typeof(ContentControlEx),
                                        new FrameworkPropertyMetadata(CharacterCasing.Normal, FrameworkPropertyMetadataOptions.Inherits | FrameworkPropertyMetadataOptions.AffectsMeasure),
                                        value => CharacterCasing.Normal <= (CharacterCasing)value && (CharacterCasing)value <= CharacterCasing.Upper);

        /// <summary> 
        /// Character casing of the Content
        /// </summary> 
        public CharacterCasing ContentCharacterCasing
        {
            get { return (CharacterCasing)GetValue(ContentCharacterCasingProperty); }
            set { SetValue(ContentCharacterCasingProperty, value); }
        }

        /// <summary>
        /// The DependencyProperty for the RecognizesAccessKey property. 
        /// Default Value: false 
        /// </summary> 
        public static readonly DependencyProperty RecognizesAccessKeyProperty =
            DependencyProperty.Register("RecognizesAccessKey",
                                        typeof(bool),
                                        typeof(ContentControlEx),
                                        new FrameworkPropertyMetadata(false));

        /// <summary> 
        /// Determine if the inner ContentPresenter should use AccessText in its style
        /// </summary> 
        public bool RecognizesAccessKey
        {
            get { return (bool)GetValue(RecognizesAccessKeyProperty); }
            set { SetValue(RecognizesAccessKeyProperty, value); }
        }

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

对于这种拓展依赖属性的,我全部放在ayx,命名空间改下,方便管理

image.png

迁移ControlsHelper,它提供了一些附加属性,便捷管理共用属性,文本框内部的宽度过时,我删除了

image.png

迁移WindowSettings.cs文件,这个应该为window提供上次关闭位置的功能的


这个窗体还牵扯了,Flyout和dialog窗体,涉及太多了,不列举了,先迁移


最后,我用的Controlzex应该是最新的,所以用的也必须是最新的mahapps.metro,那个4.0的metro很多属性都没有了


配合最新二者github源码,编译过了最新的core3项目为 .net4.0的wpf项目,我只需要window

image.png

通过Themes,迁移了Dialog,Flyout,DropDownButton,SplitButton,还有个metroWindow

还有个主题东西,目前编译为4.0通过,我是截止为2020-4-14 最新的github项目扣下的代码,当然还有自己的修改,才能在4.0上编译通过


下节课,开始探讨使用这个,还有改这个。


 AYUI       www.ayjs.net      AY         杨洋原创编写,请不要转载谢谢
































推荐您阅读更多有关于“”的文章

猜你喜欢

额 本文暂时没人评论 来添加一个吧

发表评论

必填

选填

选填

必填

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

  查看权限

抖音号:wpfui,可以看到我的很多作品效果

AYUI8社区版Github地址:前往获取

作者:杨洋(AaronYang简称AY,安徽六安人)目前是个人,还没公司AY唯一QQ:875556003和AY交流

高中学历,2015年1月17日开始,兴趣学习研究WPF,目前工作繁忙,不接任何活

声明:AYUI7个人与商用免费,源码可购买。部分DEMO不免费.AY主要靠卖技术服务挣钱

不是从我处购买的ayui7源码,我不提供任何技术服务,如果你举报从哪里买的,我可以帮你转正为我的客户,并送demo

查看捐赠

AYUI7.X MVC教程 更新如下:

第一课 第二课 程序加密教程

兼容XP到win10,vs2015/2017/2019,最新AYUI:7.6.5.5

vs2015 企业版密钥HM6NR-QXX7C-DFW2Y-8B82K-WTYJV

vs2017 企业版密钥NJVYC-BMHX2-G77MM-4XJMR-6Q8QF

标签列表