也许这是一个简单的问题,但不幸的是我找不到明确的答案。创建静态 viewModel 或在静态类中创建 ViewModel 并在不同的地方使用它是正确的方法吗?
例如,我想在我的一个屏幕上显示串行通信的数据。
为了避免复杂性,我创建了一个类似于我自己的项目的简单示例。串行通信开始,我创建了一个场景,就好像有连续的数据流一样。
以下数据绑定正确吗?如果不是,正确的做法应该是怎样的?
预先感谢您的帮助。
主窗口.xaml
<Grid>
<StackPanel>
<Button Command="{Binding ButtonCommandEvent}" Content="Click"/>
<TextBox Text="{Binding Counter}"/>
</StackPanel>
</Grid>
Run Code Online (Sandbox Code Playgroud)
主窗口.cs
public MainWindow()
{
InitializeComponent();
DataContext = Globals.mainWindowViewModel;
}
Run Code Online (Sandbox Code Playgroud)
主窗口视图模型
public class MainWindowViewModel : ViewModelBase
{
private int _counter;
public int Counter
{
get => _counter;
set => SetProperty(ref _counter, value);
}
Communication communication = new Communication();
public RelayCommand ButtonCommandEvent { get; set; }
public MainWindowViewModel()
{
ButtonCommandEvent = new RelayCommand(ButtonEventClick);
}
private void ButtonEventClick(object param)
{
communication.Serial_Connect();
}
}
Run Code Online (Sandbox Code Playgroud)
通讯.cs
class Communication
{
DispatcherTimer dispatcherTimer = new DispatcherTimer();
public void Serial_Connect()
{
dispatcherTimer.Interval = TimeSpan.FromSeconds(1);
dispatcherTimer.Tick += DispatcherTimer_Tick;
dispatcherTimer.Start();
}
private void DispatcherTimer_Tick(object sender, EventArgs e)
{
Globals.mainWindowViewModel.Counter = Globals.mainWindowViewModel.Counter + 1;
}
}
Run Code Online (Sandbox Code Playgroud)
全局变量
public class Globals
{
public static MainWindowViewModel mainWindowViewModel { get; } = new MainWindowViewModel();
}
Run Code Online (Sandbox Code Playgroud)
您的解释不足以给出准确的答案。
\n为此,我们需要知道为什么需要对 ViewModel 实例的全局引用。
因此,我将描述几个选项。
\n1)如果:
\n那么在这种情况下就值得使用 Singleton。
\n例子:
\npublic class MainWindowViewModel : ViewModelBase\n{\n // The only instance available outside of this class.\n public static MainWindowViewModel Instanse { get; }\n = new MainWindowViewModel();\n\n // All constructors must be MANDATORY HIDDEN.\n private MainWindowViewModel()\n {\n // Some code\n }\n\n // Some code\n}\nRun Code Online (Sandbox Code Playgroud)\n要在 XAML 中获取此实例,请使用 x: Static。
\n您可以获取整个实例,或创建到单独属性的绑定。
<SomeElement\n DataContext="{x:Static vm:MainWindowViewModel.Instance}"/>\n<SomeElement\n Command="{Binding ButtonCommandEvent,\n Source={x:Static vm:MainWindowViewModel.Instance}}"/>\nRun Code Online (Sandbox Code Playgroud)\n2)如果:
\n在这种情况下,您应该使用具有单个实例的静态类。
\n此静态类是在当前程序集中创建的。
\n通常它是一个 View 项目。
\n您的“全局类”是此类实现的一个示例。
XAML 中的用法示例:
\n<SomeElement\n DataContext="{x:Static local:Globals.MainWindowViewModel}"/>\n<SomeElement\n Command="{Binding ButtonCommandEvent,\n Source={x:Static local:Clobals.MainWindowViewModel}}"/>\nRun Code Online (Sandbox Code Playgroud)\n3)如果:
\n在这种情况下,值得将静态类与 ViewModel 的当前实例一起使用,并提供此实例替换的通知。
\n这种实现的一个例子:
\npublic static class Globals\n{\n private static MainWindowViewModel _mainWindowViewModel = new MainWindowViewModel();\n\n public static MainWindowViewModel MainWindowViewModel\n {\n get => _mainWindowViewModel;\n set => Set(ref _mainWindowViewModel, value);\n }\n public static event EventHandler<PropertyChangedEventArgs> StaticPropertyChanged;\n private static void RaisePropertyChanged([CallerMemberName] string propertyName = null)\n {\n StaticPropertyChanged?.Invoke(null, new PropertyChangedEventArgs(propertyName));\n }\n\n private static void Set<T>(ref T propertyFiled, in T newValue, [CallerMemberName] in string propertyName = null)\n {\n if (!Equals(propertyFiled, newValue))\n {\n propertyFiled = newValue;\n RaisePropertyChanged(propertyName);\n }\n }\n}\nRun Code Online (Sandbox Code Playgroud)\nXAML 中的用法示例:
\n<SomeElement\n DataContext="{Binding Path=(local:Globals.MainWindowViewModel)}"/>\n<SomeElement\n Command="{Binding Path=(local:Globals.MainWindowViewModel).ButtonCommandEvent}"/>\nRun Code Online (Sandbox Code Playgroud)\n4) 如果仅需要应用程序中的所有窗口,那么最好在应用程序资源中实例化 ViewModel。
\n这种实现的一个例子:
\n<Application x:Class="***.App"\n ---------------------\n --------------------->\n <Application.Resources>\n <local:MainWindowViewModel x:Key="mainViewModel"/>\n </Application.Resources>\n</Application>\nRun Code Online (Sandbox Code Playgroud)\nXAML 中的用法示例:
\n<SomeElement\n DataContext="{StaticResource mainViewModel}"/>\n<SomeElement\n Command="{Binding ButtonCommandEvent,\n Source={StaticResource mainViewModel}}"/>\nRun Code Online (Sandbox Code Playgroud)\n5) 如果应用程序中的所有窗口都需要此功能,但您需要能够替换实例,或者创建实例时您需要一个带有应用程序启动后计算的参数的构造函数,那么最好创建一个额外的实例类将提供此实例以及所有 Windows 所需的其他数据。
\n这种实现的一个例子:
\npublic class Locator : INotifyPropertyChanged\n{\n private MainWindowViewModel _mainWindowViewModel = new MainWindowViewModel();\n\n public MainWindowViewModel MainWindowViewModel\n {\n get => _mainWindowViewModel;\n set => Set(ref _mainWindowViewModel, value);\n }\n\n #region INotifyPropertyChanged\n public event PropertyChangedEventHandler PropertyChanged;\n private void RaisePropertyChanged([CallerMemberName] string propertyName = null)\n {\n PropertyChanged?.Invoke(null, new PropertyChangedEventArgs(propertyName));\n }\n\n private void Set<T>(ref T propertyFiled, in T newValue, [CallerMemberName] in string propertyName = null)\n {\n if (!Equals(propertyFiled, newValue))\n {\n propertyFiled = newValue;\n RaisePropertyChanged(propertyName);\n }\n }\n #endregion\n}\nRun Code Online (Sandbox Code Playgroud)\n<Application x:Class="***.App"\n ---------------------\n --------------------->\n <Application.Resources>\n <local:Locator x:Key="locator">\n <local:Locator.MainWindowViewModel>\n <local:MainWindowViewModel/>\n </local:Locator.MainWindowViewModel>\n </local:Locator>\n </Application.Resources>\n</Application>\nRun Code Online (Sandbox Code Playgroud)\n或者:
\n<Application x:Class="***.App"\n ---------------------\n ---------------------\n Startup="OnStartup">\n <Application.Resources>\n <local:Locator x:Key="locator"/>\n </Application.Resources>\n</Application>\nRun Code Online (Sandbox Code Playgroud)\npublic partial class App : Application\n{\n\n private void OnStartup(object sender, StartupEventArgs e)\n {\n Locator locator = (Locator)Resources["locator"];\n\n // Some Code\n\n locator.MainWindowViewModel = new MainWindowViewModel(/* Some Parameters*/);\n }\n}\nRun Code Online (Sandbox Code Playgroud)\nXAML 中的用法示例:
\n<SomeElement\n DataContext="{Binding MainWindowViewModel,\n Source={StaticResource locator}}"/>\n<SomeElement\n Command="{Binding MainWindowViewModel.ButtonCommandEvent,\n Source={StaticResource locator}"/>\nRun Code Online (Sandbox Code Playgroud)\n关于“通讯”课。\n它不能直接与 UI 元素一起工作,因此不需要在其中使用“DispatcherTimer”。
\n主线程(即 DispatcherTimer 使用的)执行许多任务,并且不需要加载您自己的任务。
\n将 DispatcherTimer 替换为任何异步计时器:\nSystem.Timers.Timer、System.Threading.Timer 等。
| 归档时间: |
|
| 查看次数: |
2138 次 |
| 最近记录: |