1. 项目框架
MVVM是Model、View、ViewModel的简写,这种模式的引入就是使用ViewModel来降低View和Model的耦合,说是降低View和Model的耦合。也可以说是是降低界面和逻辑的耦合,理想情况下界面和逻辑是完全分离的,单方面更改界面时不需要对逻辑代码改动,同样的逻辑代码更改时也不需要更改界面。同一个ViewModel可以使用完全不用的View进行展示,同一个View也可以使用不同的ViewModel以提供不同的操作。
Assets
…Fonts
…Images
…Styles
Common(通用类)
Converter(转换器)
DataAccess
Model
View
ViewModel
2. XAML
Window属于ContentControl(内容控件),一个内容控件只能容纳一个内容,如grid
属性:
ShowInTaskbar 窗口是否具有任务栏按钮
WindowStartupLocation 窗口启动位置
WindowState 窗口最大化最小化显示
TopMost Icon
事件
Loaded
Closing
MouseDoubleClick
2.1. 窗体圆角
更改window 窗体属性AllowTransParency为True,BackGround为Transparent,OpacityMask为White,这样设置才能保证当我们设置为圆角的时候,四个角能够透明显示
只需要在原来的Grid同级加个Border,然后再Grid和Bordr的外层加个Grid即可BorderThickness用来表示Border的粗细程度,BorderBrush用来表示Border的颜色,CornerRadius表明四个角的弯曲度
2.2. 窗体继承
https://www.cnblogs.com/zhouyinhui/archive/2008/03/16/1108561.html
https://www.cnblogs.com/ApolloSun/archive/2010/03/23/1692744.html
需要单独创建一个资源字典类型的xaml文件和配套的cs文件
2.2. Binding 和 字符串拼接
<Grid>
<TextBlock HorizontalAlignment="Left" Margin="51,114,0,0" TextWrapping="Wrap" Text="{Binding Text, ElementName=textBox, StringFormat=Test:\{0\}}" VerticalAlignment="Top"/>
</Grid>
2.3. Backgroud Binding 是字符串格式,不是Brush类型
https://blog.csdn.net/jolieLi2019888/article/details/89248418
<Button Content="{Binding BtnTestContent}" Command="{Binding StartTestCommand}" Background="{Binding BtnTestBackground}"/>
BtnTestBackground = "#673AB7";
2.4. button圆角
<!--按钮-->
<Button Grid.Row="3" Grid.Column="2" Content="取消" Margin="30,40,200,40" >
<Button.Template >
<ControlTemplate TargetType="{x:Type Button}" >
<Border BorderBrush="{TemplateBinding Control.BorderBrush}" BorderThickness="1" CornerRadius="7,7,7,7">
<Border.Background>#FFDDDDDD</Border.Background>
<ContentPresenter Content="{TemplateBinding ContentControl.Content}" HorizontalAlignment="Center" VerticalAlignment="Center" ></ContentPresenter>
</Border>
</ControlTemplate>
</Button.Template>
</Button>
2.5. XML的转义字符
https://www.cnblogs.com/wuzhenyi/archive/2013/01/13/2858797.html
1. 在XAML的后台文件中加入代码
Me.TextBlock1.Text = "AAAAAAA " + vbCrLf + "BBBBBBBB"
this.TextBlock1.Text = "AAAAAAA\nBBBBBBBB";
2. 前端可以用下面的转义字符
空格 ( )
Tab (	)
回车 (
)
换行 (
)
2.6. 取消全局样式
https://blog.csdn.net/rrzhaobaojun/article/details/11935157
Style="{x:Null}"取消模版button的style在这个模版里就可以了
2.7. 视觉状态管理器
一个VisualStateGroup里面的VisualState是互斥的
- 自定义控件通过下面的方式更改状态
: VisualStateManager.GoToState(d as NumericBoxControl, “state1”, true);- 在viewmodel 里更改状态
https://stackoverflow.com/questions/6002046/binding-visualstatemanager-view-state-to-a-mvvm-viewmodel
<i:Interaction.Triggers>
<ei:DataTrigger Binding=“{Binding StatusName}” Value=“{Binding StatusName}”>
<ei:GoToStateAction StateName=“{Binding StatusName}” />
</ei:DataTrigger>
</i:Interaction.Triggers>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="state1">
<Storyboard>
<ColorAnimation
Storyboard.TargetName="PART_Value"
Storyboard.TargetProperty="Foreground.Color"
To="Green"
Duration="0:0:0.1" />
</Storyboard>
</VisualState>
<VisualState x:Name="state2">
<Storyboard>
<ColorAnimation
Storyboard.TargetName="PART_Value"
Storyboard.TargetProperty="Foreground.Color"
To="Red"
Duration="0:0:0.1" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
2.8. Converter
.Net提供了两种Converter接口,单值转换的接口IValueConverter和多值转换的接口IMultiValueConverter,
1. xaml引用命名空间 xmlns:converter="clr-namespace:WpfApp1.Converter"
2. xaml定义resources
<Window.Resources>
<converter:GenderConverter x:Key="genderConverter" />
</Window.Resources>
3. Converter文件夹下添加 GenderConverter.cs 文件,继承IValueConverter接口,实现类
public class GenderConverter : IValueConverter
{
//Model 向 View 转换
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null || parameter == null)
{
return false;
}
return value.ToString() == parameter.ToString();
}
//View 向 Model 转换
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return parameter;
}
}
4. 控件添加Converter
<RadioButton
IsChecked="{Binding UserInfo.Gender, Converter={StaticResource genderConverter}, ConverterParameter=1}" />
2.9. Animation(动画)
https://blog.csdn.net/ajian11/article/details/82504629
共有三种类型的动画(线性/关键帧/路径),在System.Windows.Media.Animation名称空间中将会发现以下内容:
17个线性插值动画类,这些类使用线性插值动画
22个关键帧动画类,这些类使用关键帧动画
3个路径动画类,这些类使用基于路径的动画
线性动画:在一个开始值和结束值之间以逐步增加的方式(被称为线性插值的过程)改变属性的动画,DoubleAnimation动画类和ColorAnimation动画类属于第一种动画,它们使用插值平滑地改变数值
关键帧动画:从一个值突然改变到另外一个值的动画,所有的关键帧动画类都使用"类型名+AnimationUsingKeyFrames"的形式进行命名,如StringAnimationUsingKeyFrames类和ObjectAnimationUsingKey Frames类
路径的动画:基于路径的动画修改数值使其符合由PathGeometry对象描述的形状,并且它主要用于沿着路径移动元素。基于路径的动画类使用"类型名+AnimationUsingPath"的形式进行命名,如DoubleAnimationUsingPath动画类和PointAnimationUsingPath动画类
例子1
https://blog.csdn.net/weixin_44870681/article/details/93660976
- 在<Window.Resources>下添加
<Storyboard x:Key="sbkey">
<!--线性-->
<DoubleAnimation From="1.0" To="0.0" Duration="0:0:1" Storyboard.TargetName="Bd" Storyboard.TargetProperty="Opacity">
</DoubleAnimation>
<!--线性-->
<ColorAnimation From="White" To="Orange" Duration="0:0:2" Storyboard.TargetName="Bd" Storyboard.TargetProperty="Background">
</ColorAnimation>
<!--离散-->
<ColorAnimationUsingKeyFrames
RepeatBehavior="Forever"
Storyboard.TargetName="StatusLED"
Storyboard.TargetProperty="Fill.Color">
<DiscreteColorKeyFrame KeyTime="0:0:0.5" Value="Green" />
<DiscreteColorKeyFrame KeyTime="0:0:1" Value="Gray" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
- 在<Window.triggers>下添加
<EventTrigger RoutedEvent="Button.Click" Sourcename="button">
<BeginStoryboard Storyboard="{staticResource sbkey}" />
</EventTrigger>
例子2
某个控件沿着规划路径移动
<Window.Resources>
<PathGeometry Figures="M0,0 100,100 500,100 600,200" x:Key="path"/>
<Storyboard x:Key="sb">
<PointAnimationusingPath Storyboard.TargetName="eg" Duration="0:0:5" Storyboard.TargetProperty="Center"/>
</Storyboard>
</Window.Resources>
<Window.Triggers>
<EventTrigger RouteEvent="Window.Loaded">
<BeginStroyboard Storyboard="{StaticResource sb}">
</EventTrigger>
</Window.Triggers>
<Grid>
<Path Data="{StaticResource path}" Stroke="Red" StrokeThickness="1"/>
<Path Fill="Orange">
<Path.Data>
<EllipseGeometry Center="0,0" RadiusX="60" RadiusY="30" x:Name="eg"/>
</Path.Data>
</Path>
</Grid>
2.10. 事件触发器
在Style下的触发器只能操作自身,Style.Triggers
在控件下的触发器可以操作同级的控件,控件.Triggers
2.11. 定义系统的整体颜色方案
https://blog.csdn.net/weixin_43876816/article/details/115694445
<Application.Resources>
<ResourceDictionary>
<SolidColorBrush x:Key="DefultWindowBG" Color="#FF1991EC"/>
</ResourceDictionary>
</Application.Resources>
<Label
Content="{DynamicResource UserLabel}"
Foreground="{DynamicResource DefultWindowBG}" >
<Label/>
2.12. listview控件绑定右键菜单命令
https://blog.csdn.net/u014650759/article/details/103722164
2.13. 拖动改变ListView行数据顺序
https://www.cnblogs.com/zhangyongheng/p/4065427.html
2.14. ListViewItem双击事件绑定到Command
https://www.cnblogs.com/yang-fei/p/5419000.html
2.15. ListView根据显示内容更改行的背景色
https://www.cnblogs.com/changbaishan/p/3308045.html
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<!-- 设置触发器 -->
<Style.Triggers>
<DataTrigger Binding="{Binding Path=RunStatus}" Value="False">
<Setter Property="Background" Value="Gray" />
</DataTrigger>
<!--<Trigger Property="IsSelected" Value="true">
<Setter Property="Background" Value="Red"/>
<Setter Property="Foreground" Value="White"/>
</Trigger>-->
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
2.16. ListView根据显示内容更改ContextMenu MenuItem
<ListView
Name="listView1"
ItemsSource="{Binding FlowViewDataList}">
<ListView.Resources>
<Style x:Key="CheckMenuItem" TargetType="{x:Type MenuItem}">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}, Path=PlacementTarget.SelectedItem.RunStatus}" Value="True">
<Setter Property="Header" Value="禁用" />
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}, Path=PlacementTarget.SelectedItem.RunStatus}" Value="False">
<Setter Property="Header" Value="启用" />
</DataTrigger>
</Style.Triggers>
</Style>
</ListView.Resources>
<ListView.ContextMenu>
<ContextMenu Background="{DynamicResource DefultWindowBG}">
<MenuItem
Icon="{materialDesign:PackIcon Kind=Cancel}"
Style="{StaticResource CheckMenuItem}">
</MenuItem>
</ContextMenu>
</ListView.ContextMenu>
</ListView>
2.20. GridView的列宽度设置为按比例分配
<Grid>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*" />
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<Grid Grid.Column="0" x:Name="col1"/>
<Grid Grid.Column="1" x:Name="col2"/>
<Grid Grid.Column="2" x:Name="col3"/>
<Grid Grid.Column="3" x:Name="col4"/>
</Grid>
<ListView x:Name="listview">
<ListView.View>
<GridView>
<GridViewColumn Header="header1" Width="{Binding ElementName=col1,Path=ActualWidth}"/>
<GridViewColumn Header="header2" Width="{Binding ElementName=col2,Path=ActualWidth}"/>
<GridViewColumn Header="header3" Width="{Binding ElementName=col3,Path=ActualWidth}"/>
<GridViewColumn Header="header4" Width="{Binding ElementName=col4,Path=ActualWidth}"/>
</GridView>
</ListView.View>
</ListView>
</Grid>
2.30. TreeView 获取TreeViewItem
通过toolsTree_Selected事件获取
private void toolsTree_Selected(object sender, RoutedEventArgs e)
{
TreeViewItem treeViewItem = e.OriginalSource as TreeViewItem;
if (treeViewItem == null || e.Handled) return;
treeViewItem.IsExpanded = !treeViewItem.IsExpanded;
//treeViewItem.IsSelected = false;
e.Handled = true;
}
2.31. TreeView
https://www.cnblogs.com/cplemom/p/12078859.html
2.32. Style BaseOn
如果想在别的样式基础上,进行修改,用BasedOn
<TreeView.ItemContainerStyle>
<Style BasedOn="{StaticResource MaterialDesignTreeViewItem}" TargetType="{x:Type TreeViewItem}">
<Setter Property="IsExpanded" Value="True" />
</Style>
</TreeView.ItemContainerStyle>
2.33. InvokeCommandAction.CommandParameter传递多个参数
https://www.jianshu.com/p/873789538140
cs
/// <summary>
/// 用于从Xml中AddCoilCommand事件命令传递多参数转换
/// </summary>
class MultiValueConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
List<object> list = new List<object>();
foreach (object value in values)
{ if (value == null) return null;
list.Add(value);
}
return list;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
xaml
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary>
<common:MultiValueConverter x:Key="multiValueConverter" />
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDoubleClick">
<i:InvokeCommandAction Command="{Binding DGMouseDoubleClickCommand}">
<i:InvokeCommandAction.CommandParameter>
<MultiBinding Converter="{StaticResource ResourceKey=multiValueConverter}">
<Binding ElementName="DG_TestBoard" Path="SelectedItem" />
<Binding ElementName="DG_TestBoard" Path="CurrentColumn" />
<Binding ElementName="DG_TestBoard" Path="SelectedIndex" />
</MultiBinding>
</i:InvokeCommandAction.CommandParameter>
</i:InvokeCommandAction>
</i:EventTrigger>
</i:Interaction.Triggers>
3. 基础设置
<Windows
Title="系统登录" Height="600" Width="360"
FontFamily="Microsoft YaHei" FontWeight="ExtraLight"
ResizeMode="NoResize"
WindowStartupLocation="CenterScreen"
WindowStyle="None" AllowsTransparency="True"
Background="{x:Null}" > 无边框,无背景
**窗体四周小边框**
<Border Margin="5" Background="White" CornerRadius="10">
<Border.Effect>
<DropShadowEffect Color="Gray" ShadowDepth="0" BlurRadius="5" Opacity="0.3" Direction="0" />
</Border.Effect>
</Border>
3.1WPF关闭应用程序,释放Window窗口资源方法
https://blog.csdn.net/hujianwind/article/details/9351183
WindowsForm里一个Application.Exit();方法就可以关闭应用程序,释放掉资源。
WPF里Application类没有该方法,但是有一个Exit的事件驱动,在WPF应用程序里面关闭程序讲究很多:
在WPF应用程序的关闭是有ShutdownMode属性设置,具有3中枚举类型的值:
1)OnLastWindowClose 应用程序最后一个窗体关闭时关闭应用程序
2)OnMainWindowClose 应用程序主窗体关闭时关闭应用程序
3)OnExplicitShutdown 显示调用关闭
在OnExplicitShutdown模式下必须显示调用Application实例的ShutDown方法
3.2 DataGrid
3.2.1 表格按钮绑定事件
传的参数为当前行
<DataGridTemplateColumn Header="操作" MinWidth="120">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Content="{Binding OperationString}"
Command="{Binding DataContext.VideoOperationCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid}}"
CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid}, Path=SelectedItem}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
传的参数为整个datagrid
<Button Content="Set" Uid="{Binding Id}" HorizontalAlignment="Center" VerticalAlignment="Center"
Style="{StaticResource SetButtonStyle}" Width="50" Background="#007DFA"
Command="{Binding DataContext.SetClickCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid}}"
CommandParameter="{Binding ElementName=pduData}" >
</Button>
3.2.2 获取 DataTemplate 里面的控件
DataGrid dataGrid = (DataGrid)obj;
DataGridTemplateColumn templeColumn = dataGrid.Columns[0] as DataGridTemplateColumn;
FrameworkElement element;
CheckBox checkBox;
for(int i = 0; i < dataGrid.Items.Count; i++)
{
element = dataGrid.Columns[0].GetCellContent(dataGrid.Items[i]);
checkBox = templeColumn.CellTemplate.FindName("checkPDU", element) as CheckBox;
Console.WriteLine(checkBox.IsChecked.ToString());
}
3.2.3 绑定ItemsSource=“{Binding Collection,Mode=TwoWay}”
数据源的绑定方式是OneWay, 前端更改了数据,是不能同步到后端的,
如果需要同步到后端,可以在具体的cell 添加UpdateSourceTrigger=PropertyChanged,比如下面的
IsChecked=“{Binding IsChecked, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}”
3.2.4 自动滚动到最新行
public OneDimensionalCodeFuncView()
{
InitializeComponent();
((ICollectionView)this.DataGridOneDC.Items).CollectionChanged += QueryBusinessLevelWindow_CollectionChanged;
}
private void QueryBusinessLevelWindow_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)//新增数据时才出发滚动
this.DataGridOneDC.ScrollIntoView(this.DataGridOneDC.Items[this.DataGridOneDC.Items.Count - 1]);
}
3.2.5 采用handycontrol的样式
添加样式资源,一般是在App.xaml里添加,如果样式被覆盖了,可以在DataGrid所在的xaml页面添加
<ResourceDictionary.MergedDictionaries>
<hc:ThemeResources />
<hc:Theme />
</ResourceDictionary.MergedDictionaries>
居中的样式
<Style
x:Key="DataGridTextCenterRowHeaserStyle"
BasedOn="{StaticResource DataGridRowHeaderStyle}"
TargetType="DataGridRowHeader">
<Setter Property="HorizontalContentAlignment" Value="Center" />
</Style>
<Style
x:Key="DataGridTextCenterColumnStyle"
BasedOn="{StaticResource DataGridCellStyle}"
TargetType="DataGridCell">
<Setter Property="HorizontalContentAlignment" Value="Center" />
</Style>
<Style
x:Key="DataGridTextCenterColumnHeaderStyle"
BasedOn="{StaticResource DataGridColumnHeaderStyle}"
TargetType="DataGridColumnHeader">
<Setter Property="HorizontalContentAlignment" Value="Center" />
</Style>
<DataGrid
x:Name="DataGridOneDC"
Width="390"
Height="300"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
hc:DataGridAttach.ShowRowNumber="True"
AutoGenerateColumns="False"
HeadersVisibility="All"
HorizontalScrollBarVisibility="Disabled"
IsReadOnly="True"
ItemsSource="{Binding OneDimensionalCodeDataCollection}"
RowHeaderStyle="{StaticResource DataGridTextCenterRowHeaserStyle}"
RowHeaderWidth="30">
<DataGrid.Columns>
<DataGridTextColumn
Width="17*"
Binding="{Binding Content}"
CellStyle="{StaticResource DataGridTextCenterColumnStyle}"
Header="解码字符串"
HeaderStyle="{StaticResource DataGridTextCenterColumnHeaderStyle}" />
</DataGrid.Columns>
</DataGrid>
3.3 MouseLeftButtonDown事件失效的问题
控件在捕获了MouseLeftButtonDown事件后,会将该事件的“Handled”设置为True,这个属性是用在事件路由中的,当某个控件得到一个RoutedEvent,就会检测Handled是否为true,为true则忽略该事件。
并且,控件本身的Click事件,相当于将MouseLeftButtonDown事件抑制(Supress)掉了,转换成了Click事件。所以,如果一定要使用这个事件的话,需要在初始化的函数里利用UIElement的AddHandler方法,显式的增加这个事件
public MainWindow()
{
InitializeComponent();
button_get_trade_record.AddHandler(Button.MouseLeftButtonDownEvent, new MouseButtonEventHandler(this.button_get_trade_record_MouseLeftButtonDown), true);
}
3.4 绑定用户控件中某控件的属性
https://www.bilibili.com/video/BV1UE411R7g2?p=8
使用依赖属性
3.5 播放flash动画
https://www.bilibili.com/video/BV1UE411R7g2?p=7
3.6 绑定跟踪调试
https://www.bilibili.com/video/BV1UE411R7g2?p=6
在引用里添加 xmlns:dbg=“clr-namespace:System.Diagnostics;assembly=WindowBase”
3.7 动态的复制粘贴控件
https://www.bilibili.com/video/BV1UE411R7g2?p=3
3.8 为粘贴的控件添加事件
https://www.bilibili.com/video/BV1UE411R7g2?p=6
3.9 WPF使用winform的控件
https://cloud.tencent.com/developer/article/1760996
3.10 ViewModel里获取View 里的控件对象
1. 通过loaded事件获取(下面的例子因为使用了WindowsFormsHost,不能直接绑定WindowsFormsHost下面的控件ElementName,需要先绑定WindowsFormsHost,然后通过child获取)
xmal
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<mvvm:EventToCommand Command="{Binding LoadedHWCommand}" CommandParameter="{Binding ElementName=FormHost}" />
</i:EventTrigger>
</i:Interaction.Triggers>
viewmodel
public RelayCommand<object> LoadedHWCommand { get; set; }
this.LoadedHWCommand = new RelayCommand<object>(LoadHW);
private void LoadHW(object o)
{
try
{
//获取HWindowControlWPF控件对象
form_Host = (WindowsFormsHost)o;
hWindow_Fit1 = (HWindow_Final)form_Host.Child;
}
catch (Exception)
{
throw;
}
}
2. 通过按钮的command事件获取
xmal
<Button
x:Name="Load_Pic"
Width="90"
Height="30"
Margin="0,10"
Command="{Binding LoadPicCommand}"
CommandParameter="{Binding ElementName=hwindow}"
Content="Load_Pic" />
viewmodel
public RelayCommand<object> LoadPicCommand { get; set; }
this.LoadPicCommand = new RelayCommand<object>(LoadPic);
//获取HWindowControlWPF控件对象
HWindow_Final hWindow_Fit1 = ((HWindow_Final)o);
3.11 pictureBox控件获取Resources的png
System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(Properties.Resources.查找);
IntPtr hBitmap = bmp.GetHbitmap();
System.Windows.Media.ImageSource WpfBitmap = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(hBitmap, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
this.pictureBox1.Source = WpfBitmap;
3.12 ComboBox 颜色选择器
https://blog.csdn.net/anjingyatou/article/details/18262639
通过SelectedIndex确定默认值
3.13 颜色字符串转16进制
System.Drawing.Color temp = System.Drawing.Color.FromName("red");
string temp = System.Drawing.ColorTranslator.ToHtml(System.Drawing.Color.FromArgb(temp.R, temp.G, temp.B));
3.14 wpf使用iconfont
https://blog.csdn.net/wanxiweilai/article/details/126540296
如果在设计界面可以显示但是在运行界面不显示,需要修改ttf文件的属性,设置生成操作为资源
# xaml文件里的设置
FontFamily="../Fonts/#iconfont"
Text=""
# 如果在代码里需要把 &# 改成 \
"\xe748"
3.15 引用外部程序集的资源
项目结构如下,主项目是AutoTestPlatform,AutoTest.Resource是专门放资源文件的程序集,主项目需要引用AutoTest.Resource里的资源。
1. 先把AutoTest.Resource添加到主项目中;
2. FontFamily="/AutoTest.Resource;component/Fonts/#iconfont"
3. <ResourceDictionary Source="/AutoTest.Resource;component/Styles/DefaultStyle.xaml"/>
3.16 遍历所有的空间
/// <summary>
/// 遍历所有的光开关通道
/// </summary>
private void SearchAllCheckbox(FrameworkElement container)
{
foreach (var child in LogicalTreeHelper.GetChildren(container))
{
if (child is CheckBox)
{
CheckBox cb = child as CheckBox;
if (cb.IsChecked == true)
{
checkboxList.Add(int.Parse(cb.Tag.ToString()));
}
}
FrameworkElement frameworkElement = child as FrameworkElement;
if (frameworkElement != null)
{
SearchAllCheckbox(frameworkElement);
}
}
}
3.17 Datatrigger 判断不等于
https://www.cnblogs.com/DingGuo/p/14211553.html
<Style>
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<!--<Condition 1 here.../>-->
<!--<Condition 2 here.../>-->
<Condition>
<Condition.Binding>
<Binding Path="id" Converter="{StaticResource ValueToEqualsParameterConverter}">
<Binding.ConverterParameter> //没有定义全局Style
<System:Int32>3</System:Int32> //没有定义全局Style
</Binding.ConverterParameter> //没有定义全局Style
</Binding>
</Condition.Binding>
<Condition.Value>
<System:Boolean>False</System:Boolean>
</Condition.Value>
</Condition>
</MultiDataTrigger.Conditions>
<Setter Property="Background" Value="Red" />
<Setter Property="Foreground" Value="Black" />
</MultiDataTrigger>
</Style.Triggers>
</Style>
//如果有定义全局Style,则注释上面三行,在全局Style中加入
<local:ValueToEqualsParameterConverter x:Key = "ValueToEqualsParameterConverter"/>
转换器
public class ValueToEqualsParameterConverter : IValueConverter {
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
return value.ToString() == parameter.ToString();
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
return null;
}
}
3.17 DataGrid 根据 DataTrigger 显示多种行模板
https://zhuanlan.zhihu.com/p/538510004?utm_id=0
<DataGrid x:Name="MyDataGrid" ItemsSource="{Binding DataGridList}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding Name}" IsReadOnly="True"/>
<DataGridTemplateColumn Header="Type">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ContentControl>
<ContentControl.Style>
<Style TargetType="ContentControl">
<Style.Triggers>
<!-- 当 Binding 的内容为 Value 时会触发 -->
<DataTrigger Binding="{Binding Name}" Value="TextBox">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBox Text="This is a TextBox"/>
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding Name}" Value="ComboBox">
<Setter Property="Foreground" Value="Red"/>
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<ComboBox Text="This is a ComboBox" IsEditable="True">
<ComboBoxItem Content="Item 1"/>
<ComboBoxItem Content="Item 2"/>
</ComboBox>
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding Name}" Value="TextBoxBinding">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBox Text="{Binding Content}"/>
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
4. 语法
4.1. 绑定的几种方法
ElementnName 依据Name相互绑定
Content="{Binding ElementName=txt1, path=Text}"
RelativeSource 相对于本身属性或者父元素属性
Content="{RelativeSource Mode=Self}, Path=Height"
ItemSource 绑定到集合元素
ItemSource="{Binding Collection}"
DataContext 多种不同值绑定
4.2. Show 和 ShowDialog 的区别
ShowDialog会卡住线程
4.3. 依赖属性
VS创建依赖属性快捷键 propdp
//依赖属性必须为static readonly
//DependencyProperty.Register 参数说明
//第一个参数是string类型的,是属性名。
//第二个参数是这个依赖项属性的类型。
//第三个参数是这个拥有这个依赖项属性的类型。
//第四个参数是具有附加属性设置的PropertyMetadata对象。
PropertyMetadata,FrameworkPropertyMetadata,UIPropertyMetadata
https://blog.csdn.net/Libby1984/article/details/53556721
只想通过dp支持属性并提供默认值,请使用PropertyMetadata
要指定动画行为,请使用UIPropertyMetadata
某些属性影响wpf框架级别的东西,例如元素布局,父布局或数据绑定,请使用FrameworkPropertyMetadata
4.4. Usercontrol Customtrol
https://www.bilibili.com/video/BV1q64y1U7Zk?p=12
Usercontrol 用户控件,继承与系统的控件, 控件的组装,只能使用系统自带控件的属性,
Customtrol 自定义控件,真正的控件,自定义控件属性,控件样式
xaml文件一定要放在Themes文件夹下,可以有一下这些名字,根据系统样式选择对应的xaml文件
4.5. ObservableCollection
ObservableCollection 跟 List一样使用
ObservableCollection 对象的增减可以通知界面的更新,对象内容的改变不会通知界面的更新
public ObservableCollection Collection = new ObservableCollection();
List<T>和ObservableCollection<T>的相互转换
1.ObservableCollection转换List
ObservableCollection o; // 假设已经赋值
List list = new List(o.ToList());
2.List转换ObservableCollection
List list; // 假设已经赋值
// 方法1
ObservableCollection o = new ObservableCollection(list);
//方法2
ObservableCollection o = new ObservableCollection();
list.Foreach(l => o.Add(l));
4.6. 十六进制转Brush
(SolidColorBrush)(new BrushConverter().ConvertFrom("#ffaacc"));
4.7. 跨线程更新UI
System.Windows.Application.Current.Dispatcher.Invoke(new Action(() =>
{
...........
}));
4.8. 通过Bing修改依赖属性 和 直接访问控件属性的冲突
修改一个按钮的状态
①直接通过this.but_openSerial.IsEnabled = false 修改
②通过OpenSerialEnabled = true修改
通过①修改之后,再通过②修改,不生效,不能同时采用两种方式修改
可以通过 MVVMLight学习笔记(七)—Messenger使用 都使用第二种方式修改
5. 第三方库
5.1. MaterialDesignThemes
①使用 NuGet 安裝
②修改 App.xaml
<Application.Resources>
` <ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Light.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Primary/MaterialDesignColor.DeepPurple.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Accent/MaterialDesignColor.Lime.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>`
</Application.Resources>
③修改 MainWindow.xaml
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
使用Material Design的 Picker
需要把toolkit里复制的code放到 <materialDesign:DialogHost />里面
相对应的ViewModel里添加绑定的数据
添加CombinedDialogOpenedEventHandler等函数
版本4.9.0 Snackbar 不能修改FontSize的问题,可以参考https://github.com/MichelMichels/MaterialDesignInXamlToolkit/commit/90cf05241333229fa74d4b4894c25b7b978f2669
拉取4.9.0的库,更新MaterialDesignThemes.Wpf/Themes/MaterialDesignTheme.Snackbar.xaml,重新生成dll即可``
<md:Snackbar x:Name="LoginSnakeBar" Grid.Row="3" Grid.ColumnSpan="2" Foreground="White"
Background="#673ab7" MessageQueue="{md:MessageQueue}" FontSize="13">
</md:Snackbar>
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converters="clr-namespace:MaterialDesignThemes.Wpf.Converters"
xmlns:system="clr-namespace:System;assembly=mscorlib"
xmlns:wpf="clr-namespace:MaterialDesignThemes.Wpf">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Button.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.TextBlock.xaml" />
</ResourceDictionary.MergedDictionaries>
<converters:NullableToVisibilityConverter x:Key="NullableToVisibilityConverter" />
<converters:MathMultipleConverter x:Key="MathMultipleConverter"
Operation="Multiply" />
<converters:SnackbarActionButtonPlacementModeConverter x:Key="SnackbarActionButtonPlacementModeConverter" />
<Style x:Key="MaterialDesignSnackbarActionButton"
TargetType="Button">
<Setter Property="Background"
Value="Transparent" />
<Setter Property="BorderBrush"
Value="Transparent" />
<Setter Property="BorderThickness"
Value="1" />
<Setter Property="Cursor"
Value="Hand" />
<Setter Property="FocusVisualStyle"
Value="{StaticResource FocusVisual}" />
<Setter Property="Foreground"
Value="{DynamicResource SecondaryHueMidBrush}" />
<Setter Property="Height"
Value="36" />
<Setter Property="HorizontalContentAlignment"
Value="Center" />
<Setter Property="Margin"
Value="8,-10,-8,-10" />
<Setter Property="Padding"
Value="8" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid x:Name="Root"
Background="{TemplateBinding Background}">
<wpf:Ripple Padding="{TemplateBinding Padding}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Focusable="False"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver"
Value="true">
<Setter Property="Background"
Value="{DynamicResource MaterialDesignSnackbarMouseOver}" />
</Trigger>
<Trigger Property="IsEnabled"
Value="false">
<Setter Property="Opacity"
Value="0.38" />
</Trigger>
<Trigger Property="DockPanel.Dock"
Value="Bottom">
<Setter Property="Margin"
Value="0,18,-8,-8" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="TextBlock.FontSize"
Value="14" />
<Setter Property="TextBlock.FontWeight"
Value="Medium" />
<Setter Property="VerticalAlignment"
Value="Stretch" />
<Setter Property="VerticalContentAlignment"
Value="Center" />
<Setter Property="wpf:RippleAssist.Feedback"
Value="{DynamicResource MaterialDesignSnackbarRipple}" />
</Style>
<Style x:Key="MaterialDesignSnackbarActionLightButton"
TargetType="Button"
BasedOn="{StaticResource MaterialDesignSnackbarActionButton}">
<Setter Property="Foreground"
Value="{DynamicResource PrimaryHueLightBrush}" />
</Style>
<Style x:Key="MaterialDesignSnackbarActionMidButton"
TargetType="Button"
BasedOn="{StaticResource MaterialDesignSnackbarActionButton}">
<Setter Property="Foreground"
Value="{DynamicResource PrimaryHueMidBrush}" />
</Style>
<Style x:Key="MaterialDesignSnackbarActionDarkButton"
TargetType="Button"
BasedOn="{StaticResource MaterialDesignSnackbarActionButton}">
<Setter Property="Foreground"
Value="{DynamicResource PrimaryHueDarkBrush}" />
</Style>
<Style TargetType="wpf:SnackbarMessage">
<Setter Property="HorizontalContentAlignment"
Value="Left" />
<Setter Property="Margin"
Value="16" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="wpf:SnackbarMessage">
<DockPanel>
<!-- will become a Panel to wrap a "pretend" button -->
<Button x:Name="PART_ActionButton"
HorizontalAlignment="Right"
Panel.ZIndex="1"
Command="{TemplateBinding ActionCommand}"
CommandParameter="{TemplateBinding ActionCommandParameter}"
Content="{TemplateBinding ActionContent}"
ContentStringFormat="{TemplateBinding ActionContentStringFormat}"
ContentTemplate="{TemplateBinding ActionContentTemplate}"
ContentTemplateSelector="{TemplateBinding ActionContentTemplateSelector}"
Style="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type wpf:Snackbar}}, Path=ActionButtonStyle}"
Visibility="{TemplateBinding ActionContent, Converter={StaticResource NullableToVisibilityConverter}}">
<DockPanel.Dock>
<MultiBinding Converter="{StaticResource SnackbarActionButtonPlacementModeConverter}">
<Binding Path="ActionButtonPlacement"
RelativeSource="{RelativeSource AncestorType={x:Type wpf:Snackbar}}" />
<Binding Path="(wpf:SnackbarMessage.InlineActionButtonMaxHeight)"
RelativeSource="{RelativeSource AncestorType={x:Type wpf:Snackbar}}" />
<Binding Path="ActualHeight"
RelativeSource="{RelativeSource AncestorType={x:Type wpf:Snackbar}}" />
</MultiBinding>
</DockPanel.Dock>
</Button>
<ContentPresenter MaxHeight="{Binding RelativeSource={RelativeSource AncestorType={x:Type wpf:Snackbar}}, Path=(wpf:SnackbarMessage.ContentMaxHeight)}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Content="{TemplateBinding Content}"
ContentStringFormat="{TemplateBinding ContentStringFormat}"
ContentTemplate="{TemplateBinding ContentTemplate}"
ContentTemplateSelector="{TemplateBinding ContentTemplateSelector}">
<ContentPresenter.Resources>
<DataTemplate DataType="{x:Type system:String}">
<TextBlock Padding="0"
Text="{Binding}">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}"
BasedOn="{StaticResource MaterialDesignBody1TextBlock}">
<Setter Property="TextTrimming"
Value="CharacterEllipsis" />
<Setter Property="TextWrapping"
Value="WrapWithOverflow" />
<Setter Property="FontSize"
Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type wpf:Snackbar}}, Path=FontSize}" />
<Setter Property="FontWeight"
Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type wpf:Snackbar}}, Path=FontWeight}" />
</Style>
</TextBlock.Style>
</TextBlock>
</DataTemplate>
</ContentPresenter.Resources>
</ContentPresenter>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="wpf:Snackbar">
<Setter Property="ActionButtonStyle"
Value="{StaticResource MaterialDesignSnackbarActionButton}" />
<Setter Property="Background"
Value="{DynamicResource MaterialDesignSnackbarBackground}" />
<Setter Property="ClipToBounds"
Value="True" />
<Setter Property="FontSize"
Value="14" />
<Setter Property="Foreground"
Value="{DynamicResource MaterialDesignPaper}" />
<Setter Property="HorizontalAlignment"
Value="Center" />
<Setter Property="MaxWidth"
Value="568" />
<Setter Property="MinWidth"
Value="288" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="wpf:Snackbar">
<ControlTemplate.Resources>
<Storyboard x:Key="ActivateStoryboard"
Duration="0:0:0.3">
<DoubleAnimation Storyboard.TargetName="Root"
Storyboard.TargetProperty="Tag"
From="0"
To="1"
Duration="0:0:0.3">
<DoubleAnimation.EasingFunction>
<SineEase EasingMode="EaseOut" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
<DoubleAnimation BeginTime="0"
Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Opacity"
To="0"
Duration="0" />
<DoubleAnimation BeginTime="0:0:0.075"
Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Opacity"
From="0"
To="1"
Duration="0:0:0.225">
<DoubleAnimation.EasingFunction>
<SineEase EasingMode="EaseOut" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
<Storyboard x:Key="DeactivateStoryboard"
Duration="0:0:0.3">
<DoubleAnimation Storyboard.TargetName="Root"
Storyboard.TargetProperty="Tag"
From="1"
To="0"
Duration="0:0:0.3">
<DoubleAnimation.EasingFunction>
<SineEase EasingMode="EaseOut" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</ControlTemplate.Resources>
<StackPanel x:Name="Root">
<StackPanel.Tag>
<system:Double>0.0</system:Double>
</StackPanel.Tag>
<StackPanel.Height>
<MultiBinding Converter="{StaticResource MathMultipleConverter}">
<Binding ElementName="ContentBorder"
Path="ActualHeight" />
<Binding Path="Tag"
RelativeSource="{RelativeSource Self}" />
</MultiBinding>
</StackPanel.Height>
<Border x:Name="ContentBorder"
MinHeight="48"
VerticalAlignment="Stretch"
Background="{TemplateBinding Background}"
CornerRadius="3"
SnapsToDevicePixels="True">
<ContentPresenter x:Name="ContentPresenter"
Margin="{TemplateBinding Padding}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Content="{TemplateBinding Message}" />
</Border>
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsActive"
Value="True">
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource ActivateStoryboard}" />
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource DeactivateStoryboard}" />
</Trigger.ExitActions>
</Trigger>
<Trigger Property="HorizontalAlignment"
Value="Stretch">
<Setter TargetName="ContentBorder"
Property="CornerRadius"
Value="0" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="VerticalAlignment"
Value="Bottom" />
<Setter Property="VerticalContentAlignment"
Value="Center" />
<Style.Triggers>
<Trigger Property="HorizontalAlignment"
Value="Stretch">
<Setter Property="MaxWidth"
Value="{x:Static system:Double.MaxValue}" />
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
5.2. HeBianGu
https://blog.csdn.net/u010975589/article/details/103083605
添加HeBianGu.Base.WpfBase.dll 和 HeBianGu.General.WpfControlLib.dll 两个dll文件(下载地址),在App.xml文件里添加下面内容
<ResourceDictionary.MergedDictionaries>
<!-- 用于设置动态主题 -->
<ResourceDictionary Source="/HeBianGu.Base.WpfBase;component/Theme/Color/LightThemeResource.xaml" />
<!-- 用于设置基础资源 -->
<ResourceDictionary Source="/HeBianGu.Base.WpfBase;component/Theme/HeBianGu.Theme.Default.xaml" />
<!-- 用于设置控件样式 -->
<ResourceDictionary Source="/HeBianGu.General.WpfControlLib;component/Theme/HeBianGu.Themes.Default.xaml" />
</ResourceDictionary.MergedDictionaries>
在xaml文件中添加引用 xmlns:h=“leoh”
打开HeBianGu-master\Product\Debug文件夹下的HeBianGu.Application.BlurWindow.exe,从里面找到你需要的控件,从HeBianGu-master\Source\Application\HeBianGu.Application.BlurWindow\TreeDictionary.xaml里面找到控件所在的xaml,模仿写法
ComboBox
<ComboBox HorizontalAlignment="Center" Width="190" Height="30" RenderTransform="{DynamicResource S.TransformGroup.Default}"
h:Cattach.Label="串 口 " ItemsSource="{Binding CollectionSerial}"
Style="{DynamicResource S.ComboBox.LabelClear}" h:Cattach.Watermark="请选择串口" />
皮肤主题
<h:ThemeSetControl Foreground="{DynamicResource S.Brush.TextForeground.White}" />
图片的放大功能
①使用 NuGet 安裝, HeBianGu.General.ImageCore
②xmlns:imagecore=“clr-namespace:HeBianGu.General.ImageCore;assembly=HeBianGu.General.ImageCore”
③代码
<TabControl>
<TabItem Header="鼠标滚轮放大">
<Grid>
<imageview:ImageCore ImageSource="{StaticResource S.ImageSource.Default}" OperateType="Default"/>
</Grid>
</TabItem>
<TabItem Header="标记矩形范围放大">
<Grid>
<imageview:ImageCore ImageSource="{StaticResource S.ImageSource.Default}" OperateType="Enlarge"/>
</Grid>
</TabItem>
<TabItem Header="标记矩形">
<Grid>
<imageview:ImageCore ImageSource="{StaticResource S.ImageSource.Default}" OperateType="Sign"/>
</Grid>
</TabItem>
<TabItem Header="放大镜">
<Grid>
<imageview:ImageCore ImageSource="{StaticResource S.ImageSource.Default}" OperateType="Bubble"/>
</Grid>
</TabItem>
</TabControl>
5.3 LiveCharts
①使用 NuGet 安裝
②xmlns:lvc=“clr-namespace:LiveCharts.Wpf;assembly=LiveCharts.Wpf”
5.4 XAML 格式化工具:XAML Styler
https://blog.csdn.net/u014453443/article/details/113754047
6. 把dll 文件放到单个的文件夹中
https://www.bilibili.com/video/BV1UE411R7g2?p=10
App.config
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="bin;bin2\subbin;bin3"/>
</assemblyBinding>
</runtime>
</configuration>
5.4 MVVMLight
关于Messager的使用
①MessageBase类型
Messenger.Default.Register(this, “MSerialInfo”, ReceiveSerialInfo);
Messenger.Default.Send(receiveStr, “SerialInfo”);
自定义类型
Messenger.Default.Register<bool[]>(this, “State”, func);
bool[] arr = { false, true};
Messenger.Default.Send(arr, “State”);
②GenericMessage类型
Messenger.Default.Register<GenericMessage<bool[]>>(this, “State”, func);
bool[] arr = { false, true};
Messenger.Default.Send<GenericMessage<bool[]>>(new GenericMessage<bool[]>(arr), “State”);
- https://www.cnblogs.com/xiaoke-/p/16730318.html