wpf控件设计时支持(3)

原文:wpf控件设计时支持(3)

  1. wpf设计时调试
  2. 编辑模型
  3. 装饰器

1.wpf设计时调试

为了更好的了解wpf设计时框架,那么调试则非常重要,通过以下配置可以调试控件的设计时代码

(1)将启动项目配置成外部的visual studio ide启动程序devenv.exe

(2)F5启动调试然后会打开一个新的visual studio ide,这个时候要记得重新打开你要调试的那个项目.

以上两个步骤就可以实现设计时调试了

2.编辑模型体系

当选中某些控件出现的设计时,这个选中的控件便成了可编辑的对象. 设计环境会传回一个ModelItem的类,这个类可以帮助你更改控件视图,用于交互.这里的做法与直接更改wpf控件有些不同,如直接改变wpf一个控件的一个属性

this.Content = "Hello";

在设计环境下,也可以获取到处在编辑状态的控件,若采取上面的做法,虽可以变更控件的视图,但却未变更控件在xaml的更改.

设计环境下所有控件的更改都封装在ModelItem类中.做法如下

//selectedContent‘s Type is ModelItem
selectedContent.Properties["Content"].SetValue("Hello");
//selectedContent.Properties[ContentControl.ContentProperty].SetValue("Hello");

selectedContent类型是ModelItem,其中用Properties索引值获取属性,有两种方式获取属性,字符串和静态项属性

在上篇介绍过控件上下文菜单的设计时做法,我们以此为基础做个示例,以ContentControl为例,如下图

共有4个操作,SetHello和SetRedForeground用于测试ModelItem变更控件视图的功能,

第三个和第四个菜单用于测试变更时事务的操作.(即要么全过,要么全不过)

以下为详细代码

public class ContentMenuProvider : PrimarySelectionContextMenuProvider
    {
        //略去构造函数添加MenuAcion的代码
       void ModelEditingScopeFailMenuAction_Execute(object sender, MenuActionEventArgs e)
       {
           ModelItem selectedContent = e.Selection.PrimarySelection;
           using (ModelEditingScope scope = selectedContent.BeginEdit("test"))
           {
               //selectedContent‘s Type is ModelItem
               selectedContent.Properties["Content"].SetValue("TextModelEditingScope");
               //wrong
               selectedContent.Properties["Foreground"].SetValue("Red");
               scope.Complete();
           }
       }

       void ModelEditingScopeMenuAction_Execute(object sender, MenuActionEventArgs e)
       {
           ModelItem selectedContent = e.Selection.PrimarySelection;
           using (ModelEditingScope scope = selectedContent.BeginEdit("test"))
           {
               selectedContent.Properties["Content"].SetValue("TextModelEditingScope");
               selectedContent.Properties["Foreground"].SetValue(Brushes.Green);
               scope.Complete();
           }
       }

       void SetRedForegroundMenuAction_Execute(object sender, MenuActionEventArgs e)
       {
           ModelItem selectedContent = e.Selection.PrimarySelection;
           selectedContent.Properties["Foreground"].SetValue(Brushes.Red);
           selectedContent.Properties[Control.ForegroundProperty].SetValue(Brushes.Red);
       }

       void SetHelloMenuAction_Execute(object sender, MenuActionEventArgs e)
       {
           ModelItem selectedContent = e.Selection.PrimarySelection;
           //ContentControl element = selectedContent.View as ContentControl;
           //selectedContent.Content = "hello";
           selectedContent.Properties["Content"].SetValue("Hello");
       }
    }

这里ModelItem通过MenuActionEventArgs传递进来.当需要事务支持时,则需要用到ModelEditingScope对象,通过ModelItem的BeginEdit方法,当全部变更完成时,则调用ModelEditingScope的Complete方法.

这里可以知道ModelItem是设计器对控件做出所有的变更的一个封装,也是wpf控件设计器的一个基础.上面介绍通过Properties索引值变更视图,具体ModelItem其他的功能可以参考msdn相关文档.

3.装饰器

上图是asp.net里面GridView控件的一个设计视图,右侧的可视化面板到了wpf控件的设计时就称为装饰器,那么这个装饰器其实就是wpf的控件,实现可视化界面对于使用者而言非常重要,可以了解该控件的常用功能,也省却了一些开发时间.不过目前wpf内置控件似乎没一个控件是具有这一功能的,只能希望下版visual studio对wpf控件时做的更好了,可怕的是我们自己无法扩展内置控件的设计时,只能等着微软来做,最可怕的是visual studio 2010把wpf设计时部分的api全变掉,那么这里就全白写了.

装饰器功能由AdornerProvider提供,我们从内置提供的PrimarySelectionAdornerProvider类派生一个装饰器.

派生类需要重写以上两个方法,当选中该设计器相关控件时,会调用Activate方法,离开时调用Deactivate方法.为了介绍装饰器的使用方法.示例将尽量简单,以介绍装饰器功能.

一般情况下,装饰器需要一下几个步骤

(1)定义一个AdornerPanel对象,并把控件相关装饰器添加到AdornerPanel中,然后将这个装饰器容器添加到AdornerProvider的Adorners属性中,这项操作在Activate方法中完成.

protected override void Activate(ModelItem item, DependencyObject view)
{
    Slider opacitySlider = new Slider();
    opacitySlider.Background = Brushes.Red;
    AdornerPanel myPanel = new AdornerPanel();
    myPanel.Children.Add(opacitySlider);
    Adorners.Add(myPanel);
    base.Activate(item, view);
}

注意Activate方法也将ModelItem传递进来,就意味着通过装饰器的方式也可以变更控件视图

(2)定位装饰器

再来看asp.net的GridView的设计时面板,其出现在控件的右侧,wpf设计时装饰器体系允许变更装饰器位置,上面做的第一个步骤并无法在视图上看到控件的装饰器,那是因为装饰器的定位问题.这个步骤必须完成.

这项工作由AdornerPlacementCollection对象来完成,再通过AdornerPanel的静态方法SetPlacements来设置装饰器的位置.

我们来看一下AdornerPlacementCollection的几个方法,初看会比较晕,无法判断几个方法的区别

以上8个方法可以看做4个方法,都是与高度宽度有关的.下面以图来说明,我们定义的控件装饰器是一个Slider控件.目前只用于演示作用,它做不了什么其他事情.

以上是原控件,装饰器建立在此基础之上,这里说明一下上面8个方法的参数,都是一致的,第一个是倍数因子,第二个偏移量

(1)设置容器大小

为了演示,所以装饰器控件以红色背景标记,以下代码添加在Activate方法后面,SizeRelativeToContentWidth && Height方法设置装饰器容器的大小,设置宽度和高度为控件内容高度和宽度的1倍

相应代码

AdornerPlacementCollection placement = new AdornerPlacementCollection();
placement.SizeRelativeToContentWidth(1, 0);
placement.SizeRelativeToContentHeight(1, 0);

AdornerPanel.SetPlacements(opacitySlider, placement);

(2)变更装饰器位置(PositionRelativeToAdornerWidth方法),倍数参数为正数则向右移,负数则向左移

代码变更为

AdornerPlacementCollection placement = new AdornerPlacementCollection();
placement.SizeRelativeToContentWidth(1, 0);
placement.SizeRelativeToContentHeight(1, 0);
placement.PositionRelativeToAdornerWidth(1, 0);
AdornerPanel.SetPlacements(opacitySlider, placement);

(3)DesiredWidth和DesiredHeight,注意在设计时,控件与容器之间也有着间距,如下红圈

SizeRelativeToAdornerDesiredWidth方法用于调整装饰器的DesiredWidth.看下图黄色红圈的位置变更,装饰器向右侧移动一个DesiredWidth,并宽度添加一个DesiredWidth.

代码变更为

AdornerPlacementCollection placement = new AdornerPlacementCollection();
placement.SizeRelativeToContentWidth(1, 0);
placement.SizeRelativeToContentHeight(1, 0);
placement.PositionRelativeToAdornerWidth(1, 0);
placement.SizeRelativeToAdornerDesiredWidth(1, 0);
AdornerPanel.SetPlacements(opacitySlider, placement);

注意PositionRelativeToAdornerWidth方法变更为PositionRelativeToContentWidth方法,那么SizeRelativeToAdornerDesiredWidth方法只会使装饰器宽度变更,而位置则不做变更.如下图

代码变更为

AdornerPlacementCollection placement = new AdornerPlacementCollection();
placement.SizeRelativeToContentWidth(1, 0);
placement.SizeRelativeToContentHeight(1, 0);
//placement.PositionRelativeToAdornerWidth(1, 0);
placement.PositionRelativeToContentWidth(1, 0);
placement.SizeRelativeToAdornerDesiredWidth(5, 0);
AdornerPanel.SetPlacements(opacitySlider, placement);

一边情况下不设置容器高度,因为控件的高度是不确定的,所以现在调整如下

现在最终代码变更为

AdornerPlacementCollection placement = new AdornerPlacementCollection();
placement.SizeRelativeToContentWidth(1, 0);
placement.PositionRelativeToAdornerWidth(1, 0);
placement.SizeRelativeToAdornerDesiredHeight(1, 0);
AdornerPanel.SetPlacements(opacitySlider, placement);

上面方法可以做多次尝试,便于好的理解.

demo下载

过年在家写的,比较乱,没有全部介绍完整.接着继续写.

原文地址:https://www.cnblogs.com/lonelyxmas/p/9938029.html

时间: 2024-10-08 18:27:47

wpf控件设计时支持(3)的相关文章

WPF 控件设计1

使用 ”用户自定义控件“ 定义自己的控件: 创建后生成一个.cs文件定义控件的逻辑,一个.xaml(Generic.xaml)定义控件的style. 在定义style时,使用数据绑定将style中的控件属性绑定到自定义控件的属性上,有两种方法: Angle="{Binding RelativeSource={RelativeSource TemplatedParent},Path=AxiAngle,Mode=TwoWay}" BorderThickness="{Templat

WPF 控件与布局

[控件到底是什么?] 程序的本质就是"数据+算法"------用户输入原始的数据,算法处理原始数据并得到结果数据.问题就在于程序如何将结果数据显示给用户.同样一组数据,你可以使用LED阵列显示出来,或者以命令行模式借助各种格式控制符(如TAB)对齐并输出,但这些都不如图形界面(GUI  Graphic User Interface)来的友好和方便.GUI的方便在于它对数据展示的直观性,程序员可以通过编程的方式将数据通过图形的方式展示出来,从而避免了用户面对一大堆复杂数据的痛苦.提高了工

WPF控件自绘——基础,Control类的定义

用于记录自己的学习WPF控件,大神请飘过... [WPF控件类继承关系图] 所有可以自定义模版的控件都是从Control继承,所以我们来看看Contorl类里面到底有些什么.为以后的控件自定义模版做好准备.废话少说先来看看WPF中Control类的定义 1 namespace System.Windows.Controls 2 { 3 public class Control : FrameworkElement 4 { 5 public static readonly DependencyPr

跟我一起学WPF(3):WPF控件基础

WPF控件简介 通过上一篇XAML语言的介绍,我们知道,XAML是一个树形结构,同样,WPF控件作为构成整个XAML树的一部分,也是一个树形结构.我们看一个简单的例子. <Button.Content> <DockPanel> <Image Source="F:\01.Code\01.MyCode\WpfApplication1\WpfApplication1\Resources\荷.jpg" Width="30"/> <T

DevExpress v15.1:WPF控件升级(四)

<下载最新版DevExpress WPF Controls v15.1.5> WPF编辑器 在Token编辑器中的Per-Pixel滚动 水平和垂直的per-pixel滚动 渐进式搜索 查找和组合框编辑器:在只读模式中渐进式搜索. WPF Tab Control Web浏览器的分页用户界面 在新的版本中,我们的WPF Tab控件可用于创建具有分页用户界面的应用程序--如同那些在当代Web浏览器中的应用程序一样.新功能包含了一个新的DXTabbedWindow组件,支持最终用户拖拽.自定义用户界

WPF控件NumericUpDown (转)

WPF控件NumericUpDown示例 (转载请注明出处) 工具:Expression Blend 2 + Visual Studio 2008 语言:C# 框架:.Net Framework 3.5 工程:WPF Windows Application 布局 设计预览 XAML代码: <UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http

WPF 控件库——可拖动选项卡的TabControl

原文:WPF 控件库--可拖动选项卡的TabControl 一.先看看效果 二.原理 1.选项卡大小和位置 这次给大家介绍的控件是比较常用的TabControl,网上常见的TabControl样式有很多,其中一部分也支持拖动选项卡,但是带动画效果的很少见.这也是有原因的,因为想要做一个不失原有功能,还需要添加动画效果的控件可不是一行代码的事.要做成上图中的效果,我们不能一蹴而就,最忌讳的是一上来就想实现所有效果. 一开始,我们最好先用Blend看看原生的TabControl样式模板部分是如何实现

WPF 控件之 Popup

1.常用属性说明 IsOpen: 布尔值,指示 Popup 控件是否显示 StaysOpen: 布尔值,指示在 Popup 控件失去焦点的时候,是否关闭 Popup 控件的显示 PopupAnimation:指示显示窗口时是否使用动画,只有在 AllowsTransparency 等于true时此属性才有用 Popup 窗口本身是一个不可见的元素,只有在窗口上放置了信息后才能显示 Popup的定位方式与一般控件的定位方法不一样, Popup 使用五个属性来设定位置信息: PlacementTar

WINFORM中加入WPF控件并绑定数据源实现跨线程自动更新

1. WINFORM中添加两个ElementHost,一个放WPF的Button,一个放WPF的TextBox.其中TextBox与数据源绑定,实现跨线程也可以自动更新,而不会出现WINFORM的TextBox控件与数据源绑定后,存在子线程中更新数据源报错(跨线程更新控件)的情况. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System