使用wpf图形设计器取代mfc单对话框的程序设计

举报
Amrf 发表于 2019/10/11 16:06:42 2019/10/11
【摘要】 当前效果:基础项目是:https://www.codeproject.com/Articles/24681/WPF-Diagram-Designer-Part-4附件我备份了一份在上一个wpf学习帖子里;上个帖子的基础项目是https://github.com/jogibear9988/DiagrammDesigner这个,但是这个版本里除了Test1的其他图形拖放到设计器里显示是不正常的,...

经过前面的测试和修改,我认为使用wpf图形设计器框架取代众多老的mfc单对话框程序的可行性是没有问题,

简单包裹一下,就可以在设计器里使用大量现有的wpf内置的控件;

wpf的数据绑定机制也能很好的优雅的完成老框架的一些功能;

图形控制器现有的操作方式更友好;

图形控制器现有的数据序列化方案可读性可扩展性都优于老框架;

--------------

目前设计器部分的功能已经进行的一些基础预验证;程序结构考虑是,设计器程序和工具程序分离成两个程序;

工具程序的多个Tab,每个tab对应一个设计器可以编辑的xml;

--------------

-------框架切换-此事不急-所以先鸽-------

--------------

/*-------------------wpf diagram designer前期了解-------------------------------------*/

记一个问题的处理:

现象是UserControl里面的Button的鼠标浮动效果没了,子的其他事件也不工作;

..........原因如下

image.png

/*========================分割线===============================*/

当前效果:

spacer.gifimage.png

基础项目是:

https://www.codeproject.com/Articles/24681/WPF-Diagram-Designer-Part-4附件我备份了一份在上一个wpf学习帖子里;

上个帖子的基础项目是https://github.com/jogibear9988/DiagrammDesigner这个,但是这个版本里除了Test1的其他图形拖放到设计器里显示是不正常的,我也没有定位到问题, 然后我直接使用原始项目并没有那样的问题;

记录一下修改和遇到的问题:

参考jogibear9988项目中Test1,

因为我想模拟一个div,修改为

<Grid>
    <Ellipse Margin="0,0,0,0" Fill="Gray" />
    <TextBlock  Margin="0,0,0,0" FontSize="30" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>

Test1的父节点是DesignerItem,右侧的属性框的SelectedObject如果直接是DesignerItem的话会显示过于多的属性,

参考https://www.codeproject.com/Articles/87715/Native-WPF-4-PropertyGrid定义DesignerItemProperty类,并作为DesignerItem的成员属性

,对于Test1同样定义继承于DesignerItemProperty的类Test1Property,Test1ProPerty实例需要挂到Test1的父DesignItem上,我是在其添加到设计器区域的时候进行挂载的,总感觉应该有更优雅的方式,先这么写了

protected override void OnVisualParentChanged(DependencyObject oldParent){
    if (this.Parent is DesignerItem){
        if (!((this.Parent as DesignerItem).property is Test1Property)) {
            (this.Parent as DesignerItem).property = new Test1Property();
            Test1Property p  = (this.Parent as DesignerItem).property as Test1Property;
            p.Text = "Test1";
            p.Width = 300;
            p.Height = 300;
            Binding binding = new Binding("Text");
            binding.Source = p;
            ((this.Content as Grid).Children[1] as TextBlock).SetBinding(TextBlock.TextProperty, binding);
        }
    }
}

Test1的点击功能测试另一个帖子已经说明了,主要是IsHitTestVisible需要打开,并且要注意可以使用this.Parent is DiagramDesigner.Toolbox区分位于工具栏的时候;

然后将<c:Test1/>添加到FlowChartStencils.xaml,即将Test1添加到了工具栏里;

DesignerCanvas是设计区Canvas画布,也就是DesignerItem的父,

public event SelectionChangedEventHandler SelectionChanged;
public void RaiseSelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (SelectionChanged != null) SelectionChanged(sender, e);
}

public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(object sender, PropertyChangedEventArgs e)
{
    if (PropertyChanged != null) PropertyChanged(sender, e);
}

在DesignerItem的OnPreviewMouseDown中调用designer.RaiseSelectionChanged(this, null),

在DesignerItem的DesignerItem_SizeChange中调用designer.RaisePropertyChanged(this, null),

在DesingerItem的构造函数中添加大小变化的回调this.SizeChanged += new SizeChangedEventHandler(DesignerItem_SizeChange),

在window1.xaml中设置回调SelectionChanged="MyDesigner_SelectionChanged"、PropertyChanged="MyDesigner_PropertyChanged"

在DesignerItem_SizeChange回调函数中

    BindingExpression bindingExpression = this.GetBindingExpression(WidthProperty);
    if (bindingExpression == null)
    {
        Binding binding = new Binding("Width");
        binding.Source = property;
        binding.Mode = BindingMode.TwoWay;
        this.SetBinding(WidthProperty, binding);
    }
    bindingExpression = this.GetBindingExpression(HeightProperty);
    if (bindingExpression == null)
    {
        Binding binding = new Binding("Height");
        binding.Source = property;
        binding.Mode = BindingMode.TwoWay;
        this.SetBinding(HeightProperty, binding);
    }
    DesignerCanvas designer = VisualTreeHelper.GetParent(this) as DesignerCanvas;
    if (designer != null)
    {
        designer.RaisePropertyChanged(this, null);
    }

为什么这么绑定呢,因为发现直接绑定一次,绑定会在ResizeThumb过程中的 Width赋值的时候被清空绑定-------这个问题还要具体研究

参考:https://stackoverflow.com/questions/11121057/set-the-binding-value-directly

Window1.xaml中增加一列放属性框,

<ScrollViewer Grid.Column="2" VerticalScrollBarVisibility="Auto">
<StackPanel  Margin="0,0,5,0">
    <wpg:WpfPropertyGrid x:Name="PropertyGrid1" 
Margin="5,5,5,5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" 
HelpVisible="{Binding ElementName=ShowDescrip, Path=IsChecked}" 
ToolbarVisible="{Binding ElementName=ShowToolbar, Path=IsChecked}"
PropertySort="{Binding ElementName=ComboSort, Path=SelectedItem}"  />
</StackPanel>
</ScrollViewer>

 为了使得控件可其属性框的变化时时保持同步,添加下面两个回调函数

private void MyDesigner_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e){
    Binding binding = new Binding("property");
    binding.Source = (sender as DesignerItem);
    binding.Mode = BindingMode.TwoWay;
    this.PropertyGrid1.SetBinding(WpfPropertyGrid.SelectedObjectProperty, binding);
    this.PropertyGrid1.RaisePropertyChanged(WpfPropertyGrid.SelectedObjectProperty, null, (sender as DesignerItem).property);
}

private void MyDesigner_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e){
    this.PropertyGrid1.RaisePropertyChanged(WpfPropertyGrid.SelectedObjectProperty, null, (sender as DesignerItem).property);
}

目前阶段,基本上就是上面这些修改了,总感觉不该这么来来回回绑定的~~

--------------------一段时间时候之后

前面来来回回绑定很大程度上是由于 base.OnVisualParentChanged(oldParent);没调,

后续继续研究发现直接在模板中进行子控件的绑定还是存在问题,在OnVisualParentChanged中进行子控件的属性绑定和事件绑定没有问题;

image.png

通过ncalc我们可以实现一些脚本动态绑定


image.png


其他参考:

How can i RaisePropertyChanged on property change?

Set the binding value directly

Issue properly removing property binding in WPF

How to update the value of a WPF binding from the C# code behind?

Remove binding in WPF using code

When update the value of a WPF binding from the C#, then binding lost

Problems with binding to Window Height and Width

Size change event for the usercontrol

C# WPF SizeChanged event doesn't update width and height when maximized

WPF Window_SizeChanged does not always allow Height to change in my scenario

具有RelativeSource和AncestorType的WPF绑定

WPF中的binding(九)- 使用Binding的RelativeSource

在WPF中如何使用RelativeSource绑定

XAML Binding to parent of data object

Type Checking: typeof, GetType, or is?

How to: Create a Binding in Code

How to resize a data template containing a rectangle?

What's the difference betwen a UserControl and a ContentControl?

How to properly set up a TwoWay Binding in wpf with Code

How to bind multiple values to a single WPF TextBlock?

WPF: Binding not working inside ContentControl

How to binding a control width by its parent control width

How to bind a property in a Style to the templated parent code behind?

Access variable in code-behind from Resources in UserControl

c# - How to bind to a resource

Bind an element to two sources

WPF bind usercontrol's property to parent's property

Bind to Parent Object Property with RelativeSource

WPF bind textblock to parent property

How do I use WPF bindings with RelativeSource?

WPF TextBlock Binding to a String

bind to a property in the parent control

How to listen for a property value change from within a usercontrol

WPF错误xmlns名称空间参考

A Guide to Cleaner XAML with Custom Namespaces and Prefixes (WPF/Silverlight)

Help with registerattached Dependency Property

Native WPF 4 PropertyGrid

Text On A Path in WPF

WPF Ellipse with BackgroundColor and Image

Custom vs User control

How to add text to the shapes in WPF


wpf调试:

https://github.com/MicrosoftDocs/visualstudio-docs/blob/master/docs/debugger/how-to-display-wpf-trace-information.md

https://wpf-tutorial.com/data-binding/debugging/

https://docs.microsoft.com/en-us/visualstudio/debugger/how-to-display-wpf-trace-information?view=vs-2019

https://stackoverflow.com/questions/9609685/debugging-wpf-events-bindings

/*========================分割线===============================*/

C# 中使用sqlite数据源

参考:

https://github.com/microsoft/WPF-Samples/tree/master/Data%20Binding/ADODataSet

https://www.codeproject.com/Articles/22165/Using-SQLite-in-your-C-Application

https://stackoverflow.com/questions/22188542/system-windows-markup-xamlparseexception-occurred-in-presentationframework-dll

/*========================分割线===============================*/

使用nuget添加sqlite引用(vs2015需要安装nuget扩展,NuGet.Tools.vsix,注意.net目标版本不要太低)

Install-Package System.Data.SQLite -Version 1.0.111

参考:

https://www.nuget.org/packages/System.Data.SQLite/

/*========================分割线===============================*/

C#异步相关

async await

使用Thread.CurrentThread.ManagedThreadId.ToString()可以发现await前后的线程id是不同的;

参考:

https://blog.csdn.net/wlk1229/article/details/81276970

https://blog.csdn.net/daguanjia11/article/details/52488847

https://blog.csdn.net/lxrj2008/article/details/78677810

https://blog.csdn.net/qin_yu_2010/article/details/88791969

https://www.codingame.com/playgrounds/4240/your-ultimate-async-await-tutorial-in-c+&cd=10&hl=en&ct=clnk&gl=sg

https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/

https://social.msdn.microsoft.com/Forums/vstudio/en-US/fb652123-bb0e-4f2e-a060-0843a7dad403/getcurrentthreadid-problem-in-c?forum=netfxbcl

https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/compiler-options/command-line-building-with-csc-exe

https://blog.csdn.net/taonull/article/details/39026373

fibers

https://stackoverflow.com/questions/31221210/fibers-vs-async-await

https://blog.csdn.net/woshiyuanlei/article/details/54426789

https://docs.microsoft.com/en-us/windows/win32/procthread/fibers

https://medium.com/software-development-2/coroutines-and-fibers-why-and-when-5798f08464fd+&cd=3&hl=en&ct=clnk&gl=sg

https://blog.csdn.net/madongchunqiu/article/details/69855744

Coroutine

Unity的c#带有的也有一些自实现

https://blog.csdn.net/a_little_a_day/article/details/78519265

https://forum.unity.com/threads/serial-ports-alternative-for-reading-data-from-serial-ports-into-unity.336326/+&cd=1&hl=en&ct=clnk&gl=sg


https://stackoverflow.com/questions/40541794/error-expected-lambda-expression

https://gist.github.com/Enichan/10736785

https://github.com/ChevyRay/Coroutines

https://github.com/KostiaChorny/Coroutines

https://github.com/eventanilha/EvCoroutine

https://github.com/zigaosolin/Coroutines

https://github.com/Ellpeck/Coroutine

C#串口操作测试

var port = new SerialPort();
port.BaudRate = 115200;
port.PortName = "Com1";
try
{
    port.Open();
    byte[] buffer = new byte[128];
    Encoding.UTF8.GetBytes("123", 0, "123".Length, buffer, 0);
    port.BaseStream.WriteTimeout = 2;
    port.BaseStream.Write(buffer, 0, 128);
    port.BaseStream.ReadTimeout = 2;
    port.BaseStream.Read(buffer, 0, 128);
    Console.WriteLine(buffer);
}
catch (Exception ex)
{
    Console.WriteLine(ex);
}

参考:

https://stackoverflow.com/questions/1243070/how-to-read-and-write-from-the-serial-port

https://docs.microsoft.com/en-us/dotnet/api/system.io.ports.serialport?view=netframework-4.8

https://stackoverflow.com/questions/49522110/how-can-i-fill-a-byte-array-with-a-string-without-creating-a-new-array

/*--------------------wpf绑定宽到自身的高-------------------------------------*/

https://stackoverflow.com/questions/29154068/how-do-i-bind-a-wpf-ellipses-height-to-its-own-width

/*--------------------wpf栅格布局-------------------------------------*/

https://www.wpf-tutorial.com/panels/grid-rows-and-columns/+&cd=2&hl=en&ct=clnk&gl=sg

https://stackoverflow.com/questions/14426211/manage-columnspan-in-a-grid

https://stackoverflow.com/questions/717299/wpf-setting-the-width-and-height-as-a-percentage-value

https://github.com/microsoft/WPF-Samples/blob/master/Graphics/ShapeElements/StretchExample.xaml

https://wpf.2000things.com/2011/11/16/431-binding-a-controls-width-to-its-height/+&cd=4&hl=en&ct=clnk&gl=sg

https://stackoverflow.com/questions/45225321/wpf-inline-style-not-setting-template-values

https://stackoverflow.com/questions/17681022/set-cornerradius-on-button-template

/*--------------------wpf grid穿透-------------------------------------*/

有时候我们有这样的需求,要求父grid不响应鼠标,但是子需要响应,可以这么写

 <Grid Background="{x:Null}">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="1*" />
        <ColumnDefinition Width="5*" />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="1*" />
        <RowDefinition Height="5*" />
    </Grid.RowDefinitions>
    <Border BorderBrush="Black" Background="#FA00EBF5" BorderThickness="2" CornerRadius="25" Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2" Grid.RowSpan="2" IsHitTestVisible="False"/>
    <Button Grid.ColumnSpan="2"  HorizontalAlignment="Right" ClickMode="Hover">
        <Button.Style>
            <Style TargetType="Button">
                <Setter Property="Background" Value="#FAEBEBF5" />
                <Setter Property="TextBlock.TextAlignment" Value="Center" />
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="Button">
                            <Border CornerRadius="30" Background="#FAEBEBF5" BorderBrush="#ccc" BorderThickness="0,1,1,0" >
                                <ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                            </Border>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
                <Style.Triggers>
                   <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="Background" Value="DarkGoldenrod"/>
                   </Trigger>
                </Style.Triggers>
        </Style>
        </Button.Style>
        <Viewbox Stretch="Uniform" Width="Auto" Height="Auto">
            <Polyline Points="10,100 30,100 30,30 50,30 50,100 70,100 70,30 90,30 90,100 110,100" Height="120" Width="120" Margin="0,0,0,0" Stroke="#A0FF0000" StrokeThickness="8" />
        </Viewbox>
    </Button>
    <TextBlock Grid.ColumnSpan="2" Grid.Row="1" Margin="0,0,0,0" FontSize="30" HorizontalAlignment="Center" VerticalAlignment="Center" Text="123" IsHitTestVisible="False"/>
</Grid>

{x:Null} will not be clickable, Transparent will. 

参考:

https://stackoverflow.com/questions/5344699/xnull-vs-transparent

https://stackoverflow.com/questions/12148286/how-can-you-set-ishittestvisible-to-true-on-a-child-of-something-where-its-set/14219895#14219895

/*--------------------wpf在代码中更新绑定值-------------------------------------*/

https://stackoverflow.com/questions/7681982/can-i-update-the-value-of-a-wpf-binding-from-the-c-sharp-code-behind

/*--------------------wpf设定默认值-------------------------------------*/

Binding="{Binding Path=Name.Length, FallbackValue=0, TargetNullValue=0}"

https://stackoverflow.com/questions/15567588/wpf-binding-default-value-for-empty-string

/*--------------------wpf ViewBox-------------------------------------*/

https://social.msdn.microsoft.com/Forums/vstudio/en-US/c70651b6-ab4d-47be-a5ae-c430e4a8126a/xaml-how-to-stretch-polyline-to-size-of-grid-cell?forum=wpf

/*--------------------wpf Polyline -------------------------------------*/

https://www.c-sharpcorner.com/UploadFile/mahesh/polyline-in-wpf/+&cd=1&hl=en&ct=clnk&gl=sg

/*--------------------wpf 颜色加深 -------------------------------------*/

https://stackoverflow.com/questions/12894605/how-to-make-specific-color-darken-or-lighten-based-on-value-in-wpf

/*--------------------wpf cs1106 -------------------------------------*/

https://stackoverflow.com/questions/41825940/cs1106-extension-method-must-be-defined-in-a-non-generic-static-class

this?

/*--------------------wpf 通过名字或者类型找子 -------------------------------------*/

https://stackoverflow.com/questions/636383/how-can-i-find-wpf-controls-by-name-or-type

/*--------------------wpf 点集合 -------------------------------------*/

https://stackoverflow.com/questions/11159239/string-of-point-to-pointcollection

/*--------------------wpf 反射 -------------------------------------*/

https://stackoverflow.com/questions/540066/calling-a-function-from-a-string-in-c-sharp

https://dzone.com/articles/how-c-reflection-works-with-code-examples+&cd=8&hl=zh-CN&ct=clnk&gl=sg

https://www.geeksforgeeks.org/what-is-reflection-in-c-sharp/+&cd=9&hl=zh-CN&ct=clnk&gl=sg

https://www.cnblogs.com/wangshenhe/p/3256657.html

https://jeremylindsayni.wordpress.com/2019/02/11/instantiating-a-c-object-from-a-string-using-activator-createinstance-in-net/+&cd=10&hl=zh-CN&ct=clnk&gl=sg

https://stackoverflow.com/questions/821365/how-to-convert-a-string-to-its-equivalent-linq-expression-tree

https://www.strathweb.com/2018/01/easy-way-to-create-a-c-lambda-expression-from-a-string-with-roslyn/+&cd=2&hl=zh-CN&ct=clnk&gl=sg

https://stackoverflow.com/questions/28827705/c-sharp-creating-an-expression-in-runtime-with-a-string

https://www.nuget.org/packages/ncalc/

https://stackoverflow.com/questions/23013542/get-the-parameters-in-an-expression-using-ncalc

https://github.com/ncalc/ncalc/wiki/Functions






【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。