提问人:Michael Riley 提问时间:11/13/2023 最后编辑:ClemensMichael Riley 更新时间:11/13/2023 访问量:63
WPF MVVM UserControl 绑定
WPF MVVM UserControl Binding
问:
大家晚上好。我与我一直在写的程序有点束缚。我的客户上周做了一些更改,我认为这些更改在 MVVM 架构中会更好地实现。事实上,我认为我的整个应用程序在 MVVM 中会更好。一开始,需求很小,所以我没有实现MVVM,因为我没有很好地实践它。
我一直在研究 stackoverflow、stack exchange、youtube 以及我能找到的几乎所有其他东西,以便在 MVVM 上快速启动。我已经阅读了许多关于UserControl绑定的帖子,但是我缺少一些拼图,需要取消阻止。因此,如果我的帖子内容在其他地方有些重复,我很抱歉。
我有我的 MainView,其中包含一个菜单项,该菜单项调用命令以显示 RS422ConfigView。在此视图中,我有 8 个 Rs422ConfigControlGroup (UseControls),其中包含 8 个其他控件,除了两个之外,其他控件都是组合框。我无法绑定这些单独的控件,以便可以访问其子控件。我预期的机械化图像如下:
我已将依赖项属性添加到我的 Rs422DeviceControlGroup.xaml.cs,如下所示:
namespace EngineeringLabUi.CustomControls
{
[INotifyPropertyChanged]
public partial class Rs422DeviceControlGroup : UserControl
{
public Rs422DeviceControlGroup()
{
InitializeComponent();
}
#region UseCheckedDp
/// Gets or sets the the ischecked property on the use checkbox
public bool UseChecked
{
get { return (bool)GetValue(UseCheckedProperty); }
set { SetValue(UseCheckedProperty, value); }
}
public object UseCheckedDp { get; set; }
/// Use checkbox dependency property
public static readonly DependencyProperty UseCheckedProperty =
DependencyProperty.Register("UseCheckedDp", typeof(bool),
typeof(Rs422DeviceControlGroup), new PropertyMetadata(""));
#endregion UseCheckedDp
#region ReadTypeDp
/// Gets or sets the the read type property on the use read type combo box
public SerialOpEnumType? ReadType
{
get { return (SerialOpEnumType)GetValue(ReadTypedProperty); }
set { SetValue(ReadTypedProperty, value); }
}
public object ReadTypeDp { get; set; }
/// Read type combo box dependency property
public static readonly DependencyProperty ReadTypedProperty =
DependencyProperty.Register("ReadTypeDp", typeof(SerialOpEnumType),
typeof(Rs422DeviceControlGroup), new PropertyMetadata(""));
#endregion ReadTypeDp
#region WriteTypeDp
/// Gets or sets the the write type property on the use write type combo box
public SerialOpEnumType? WriteType
{
get { return (SerialOpEnumType)GetValue(WriteTypeProperty); }
set { SetValue(WriteTypeProperty, value); }
}
public object WriteTypeDp { get; set; }
/// Write type combo box dependency property
public static readonly DependencyProperty WriteTypeProperty =
DependencyProperty.Register("WriteTypeDp", typeof(SerialOpEnumType),
typeof(Rs422DeviceControlGroup), new PropertyMetadata(""));
#endregion WriteTypeDp
#region BaudRateDp
/// Gets or sets the the baud rate property on the baud rate combo box
public SerialBaudRatesEnumType? BaudRate
{
get { return (SerialBaudRatesEnumType)GetValue(BaudRateProperty); }
set { SetValue(BaudRateProperty, value); }
}
public object BaudRateDp { get; set; }
/// Baud rate dependency property
public static readonly DependencyProperty BaudRateProperty =
DependencyProperty.Register("BaudRateDp", typeof(SerialBaudRatesEnumType),
typeof(Rs422DeviceControlGroup), new PropertyMetadata(""));
#endregion BaudRateDp
#region ParityDp
/// Gets or sets the the parity property on the parity combo box
public Parity? Parity
{
get { return (Parity)GetValue(ParityProperty); }
set { SetValue(ParityProperty, value); }
}
public object ParityDp { get; set; }
/// Parity dependency property
public static readonly DependencyProperty ParityProperty =
DependencyProperty.Register("BaudRateDp", typeof(Parity),
typeof(Rs422DeviceControlGroup), new PropertyMetadata(""));
#endregion ParityDp
#region DataBitsDp
/// Gets or sets the the data bits property on the data bits combo box
public SerialDataBitsEnumType? DataBits
{
get { return (SerialDataBitsEnumType)GetValue(DataBitsProperty); }
set { SetValue(DataBitsProperty, value); }
}
public object DataBitsDp { get; set; }
/// Data bits dependency property
public static readonly DependencyProperty DataBitsProperty =
DependencyProperty.Register("DataBitsDp", typeof(SerialDataBitsEnumType),
typeof(Rs422DeviceControlGroup), new PropertyMetadata(""));
#endregion DataBitsDp
#region StopBitsDp
/// Gets or sets the the parity property on the stop bits combo box
public StopBits? StopBits
{
get { return (StopBits)GetValue(StopBitsProperty); }
set { SetValue(StopBitsProperty, value); }
}
public object StopBitsDp { get; set; }
/// Stop bits dependency property
public static readonly DependencyProperty StopBitsProperty =
DependencyProperty.Register("StopBitsDp", typeof(StopBits),
typeof(Rs422DeviceControlGroup), new PropertyMetadata(""));
#endregion StopBitsDp
#region FccPositionDp
/// Gets or sets the the parity property on the stop bits combo box
public FccPositionsEnumType? FccPosition
{
get { return (FccPositionsEnumType)GetValue(FccPositionProperty); }
set { SetValue(FccPositionProperty, value); }
}
public object FccPositionDp { get; set; }
/// Stop bits dependency property
public static readonly DependencyProperty FccPositionProperty =
DependencyProperty.Register("FccPositionDp", typeof(FccPositionsEnumType),
typeof(Rs422DeviceControlGroup), new PropertyMetadata(""));
#endregion FccPositionDp
}
}
然后在我的 Rs422ConfigView.cs 中,我尝试绑定到这些依赖项属性:
x:Class="EngineeringLabUi.Views.Rs422ConfigView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:customControls="clr-namespace:EngineeringLabUi.CustomControls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:EngineeringLabUi"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:viewModels="clr-namespace:EngineeringLabUi.ViewModels"
Title="RS422 Device Configuration"
Width="auto"
Height="auto"
MinWidth="100"
MinHeight="600"
MaxWidth="1300"
MaxHeight="700"
mc:Ignorable="d">
<Window.DataContext>
<viewModels:Rs422ConfigViewModel />
</Window.DataContext>
<Window.Resources>
<DataTemplate x:Key="Rs422DeviceDataTemplate">
<customControls:Rs422DeviceControlGroup />
</DataTemplate>
</Window.Resources>
<Grid>
<StackPanel
HorizontalAlignment="Center"
VerticalAlignment="Center"
Orientation="Vertical">
<WrapPanel>
<!--#region Rs422Dev0CtrlGrp-->
<customControls:Rs422DeviceControlGroup
x:Name="Rs422Dev0CtrlGrp"
BaudRateDp="{Binding ModelBaudRate}"
DataBitsDp="{Binding ModelDataBits}"
DataContext="{Binding Rs422DeviceColl[0], Mode=OneWay}"
FccPositionDp="{Binding ModelFccPosition}"
ParityDp="{Binding ModelParity}"
ReadTypeDp="{Binding ViewModelReadType}"
StopBitsDp="{Binding ModelStopBits}"
UseCheckedDp="{Binding ViewModelUseChecked}"
WriteTypeDp="{Binding ViewModelWriteType}" />
<!--#endregion Rs422Dev0CtrlGrp-->
<!--#region Rs422Dev1CtrlGrp-->
<customControls:Rs422DeviceControlGroup
x:Name="Rs422Dev1CtrlGrp"
BaudRateDp="{Binding ModelBaudRate}"
DataBitsDp="{Binding ModelDataBits}"
DataContext="{Binding Rs422DeviceColl[1], Mode=OneWay}"
FccPositionDp="{Binding ModelFccPosition}"
ParityDp="{Binding ModelParity}"
ReadTypeDp="{Binding ViewModelReadType}"
StopBitsDp="{Binding ModelStopBits}"
UseCheckedDp="{Binding ViewModelUseChecked}"
WriteTypeDp="{Binding ViewModelWriteType}" />
<!--#endregion Rs422Dev1CtrlGrp-->
<!--#region Rs422Dev2CtrlGrp-->
<customControls:Rs422DeviceControlGroup
x:Name="Rs422Dev2CtrlGrp"
BaudRateDp="{Binding ModelBaudRate}"
DataBitsDp="{Binding ModelDataBits}"
DataContext="{Binding Rs422DeviceColl[2], Mode=OneWay}"
FccPositionDp="{Binding ModelFccPosition}"
ParityDp="{Binding ModelParity}"
ReadTypeDp="{Binding ViewModelReadType}"
StopBitsDp="{Binding ModelStopBits}"
UseCheckedDp="{Binding ViewModelUseChecked}"
WriteTypeDp="{Binding ViewModelWriteType}" />
<!--#endregion Rs422Dev2CtrlGrp-->
<!--#region Rs422Dev3CtrlGrp-->
<customControls:Rs422DeviceControlGroup
x:Name="Rs422Dev3CtrlGrp"
BaudRateDp="{Binding ModelBaudRate}"
DataBitsDp="{Binding ModelDataBits}"
DataContext="{Binding Rs422DeviceColl[3], Mode=OneWay}"
FccPositionDp="{Binding ModelFccPosition}"
ParityDp="{Binding ModelParity}"
ReadTypeDp="{Binding ViewModelReadType}"
StopBitsDp="{Binding ModelStopBits}"
UseCheckedDp="{Binding ViewModelUseChecked}"
WriteTypeDp="{Binding ViewModelWriteType}" />
<!--#endregion Rs422Dev3CtrlGrp-->
<!--#region Rs422Dev4CtrlGrp-->
<customControls:Rs422DeviceControlGroup
x:Name="Rs422Dev4CtrlGrp"
BaudRateDp="{Binding ModelBaudRate}"
DataBitsDp="{Binding ModelDataBits}"
DataContext="{Binding Rs422DeviceColl[4], Mode=OneWay}"
FccPositionDp="{Binding ModelFccPosition}"
ParityDp="{Binding ModelParity}"
ReadTypeDp="{Binding ViewModelReadType}"
StopBitsDp="{Binding ModelStopBits}"
UseCheckedDp="{Binding ViewModelUseChecked}"
WriteTypeDp="{Binding ViewModelWriteType}" />
<!--#endregion Rs422Dev4CtrlGrp-->
<!--#region Rs422Dev5CtrlGrp-->
<customControls:Rs422DeviceControlGroup
x:Name="Rs422Dev5CtrlGrp"
BaudRateDp="{Binding ModelBaudRate}"
DataBitsDp="{Binding ModelDataBits}"
DataContext="{Binding Rs422DeviceColl[5], Mode=OneWay}"
FccPositionDp="{Binding ModelFccPosition}"
ParityDp="{Binding ModelParity}"
ReadTypeDp="{Binding ViewModelReadType}"
StopBitsDp="{Binding ModelStopBits}"
UseCheckedDp="{Binding ViewModelUseChecked}"
WriteTypeDp="{Binding ViewModelWriteType}" />
<!--#endregion Rs422Dev5CtrlGrp-->
<!--#region Rs422Dev6CtrlGrp-->
<customControls:Rs422DeviceControlGroup
x:Name="Rs422Dev6CtrlGrp"
BaudRateDp="{Binding ModelBaudRate}"
DataBitsDp="{Binding ModelDataBits}"
DataContext="{Binding Rs422DeviceColl[6], Mode=OneWay}"
FccPositionDp="{Binding ModelFccPosition}"
ParityDp="{Binding ModelParity}"
ReadTypeDp="{Binding ViewModelReadType}"
StopBitsDp="{Binding ModelStopBits}"
UseCheckedDp="{Binding ViewModelUseChecked}"
WriteTypeDp="{Binding ViewModelWriteType}" />
<!--#endregion Rs422Dev6CtrlGrp-->
<!--#region Rs422Dev7CtrlGrp-->
<customControls:Rs422DeviceControlGroup
x:Name="Rs422Dev7CtrlGrp"
BaudRateDp="{Binding ModelBaudRate}"
DataBitsDp="{Binding ModelDataBits}"
DataContext="{Binding Rs422DeviceColl[7], Mode=OneWay}"
FccPositionDp="{Binding ModelFccPosition}"
ParityDp="{Binding ModelParity}"
ReadTypeDp="{Binding ViewModelReadType}"
StopBitsDp="{Binding ModelStopBits}"
UseCheckedDp="{Binding ViewModelUseChecked}"
WriteTypeDp="{Binding ViewModelWriteType}" />
<!--#endregion Rs422Dev7CtrlGrp-->
</WrapPanel>
</StackPanel>
</Grid>
上述代码中引用的 Rs422DeviceColl[7] 对象位于我的 Rs422ConfigModel.cs 中:
public Rs422ConfigModel()
{
}
/* Ok so here is a problem...After changing the User class to be called UserModel I can see that the below observable collection for Users are
* objects of the UseModel class. In my observable collection I had used the AddUserControl which is the WPF control but instead I should be using the
* UserControlModel instead which is a C# object
*/
private static ObservableCollection<Rs422ConfigModel> _rs422ConfigModel = new ObservableCollection<Rs422ConfigModel>();
public static ObservableCollection<Rs422ConfigModel> GetAddRs422Ctrl()
{
return _rs422ConfigModel;
}
// an object comes into this function from the AddUserViewModel:AddUserCtrlMethod
public static void AddRs422Ctrl(Rs422ConfigModel ctrl)
{
// This is where it is actually added to the collection
_rs422ConfigModel.Add(ctrl);
}
public bool? ModelUseChecked { get; set; }
public SerialOpEnumType? ModelReadType { get; set; }
public SerialOpEnumType? ModelWriteType { get; set; }
public SerialBaudRatesEnumType? ModelBaudRate { get; set; }
public Parity? ModelParity { get; set; }
public SerialDataBitsEnumType? ModelDataBits { get; set; }
public StopBits? ModelStopBits { get; set; }
public FccPositionsEnumType? ModelFcccPosition { get; set; }
public SerialDeviceStateEnumType? ModelState { get; set; }
}
我对何时何地为 UserControls 设置 DataContext 感到困惑。我读到我不应该直接在 UserControl 中设置它们,但所有这些 UserControls 只需要 Rs422ConfigViewModel 的 DataContext。另外,我不确定每个 UserControl 是否应该有自己的 Rs422ConfigViewModel。我也不太确定这是否是一个好问题。
我尝试过一个只有两个窗口的简单项目,但仍然无法弄清楚。我已经注册了 Udemy 课程以更快地启动,但我也没有发现这太有帮助。我希望有人能指出缺失的环节,我希望这篇文章能帮助其他有 C# 经验但没有 MVVM 的人。
我已经研究过的一些资源列表:
- “Binding”只能在 DependencyObject 的 DependencyProperty 上设置
- https://blog.scottlogic.com/2012/02/06/a-simple-pattern-for-creating-re-useable-usercontrols-in-wpf-silverlight.html
- 同时使用同一用户控件的多个实例
- https://medium.com/@mpcodes/wpf-c-mvvm-sample-application-14ffe10b5bf2
- UserControl 上的数据绑定 - WPF、MVVM
- WPF - UserControl 中的 MVVM 绑定
- WPF - MVVM - UserControl 绑定
- WPF - 绑定到同一控件实例的两个用户控件的内容
- 绑定到 UserControl DependencyProperty
- 使用 MVVM 模式在 WPF 中绑定 UserControl 命令 -https://stackoverflow.com/questions/4402100/wpf-mvvm-binding-properties-on-usercontrols-to-viewmodel-of-container
答: 暂无答案
评论