使用wpf图形设计器取代mfc单对话框的程序设计
经过前面的测试和修改,我认为使用wpf图形设计器框架取代众多老的mfc单对话框程序的可行性是没有问题,
简单包裹一下,就可以在设计器里使用大量现有的wpf内置的控件;
wpf的数据绑定机制也能很好的优雅的完成老框架的一些功能;
图形控制器现有的操作方式更友好;
图形控制器现有的数据序列化方案可读性可扩展性都优于老框架;
--------------
目前设计器部分的功能已经进行的一些基础预验证;程序结构考虑是,设计器程序和工具程序分离成两个程序;
工具程序的多个Tab,每个tab对应一个设计器可以编辑的xml;
--------------
-------框架切换-此事不急-所以先鸽-------
--------------
/*-------------------wpf diagram designer前期了解-------------------------------------*/
记一个问题的处理:
现象是UserControl里面的Button的鼠标浮动效果没了,子的其他事件也不工作;
..........原因如下
/*========================分割线===============================*/
当前效果:
基础项目是:
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中进行子控件的属性绑定和事件绑定没有问题;
通过ncalc我们可以实现一些脚本动态绑定
其他参考:
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
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
A Guide to Cleaner XAML with Custom Namespaces and Prefixes (WPF/Silverlight)
Help with registerattached Dependency Property
WPF Ellipse with BackgroundColor and Image
How to add text to the shapes in WPF
wpf调试:
https://wpf-tutorial.com/data-binding/debugging/
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
/*========================分割线===============================*/
使用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://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/
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://blog.csdn.net/madongchunqiu/article/details/69855744
Coroutine
Unity的c#带有的也有一些自实现
https://blog.csdn.net/a_little_a_day/article/details/78519265
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
/*--------------------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://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
/*--------------------wpf在代码中更新绑定值-------------------------------------*/
/*--------------------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/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
- 点赞
- 收藏
- 关注作者
评论(0)