wpf MVVM混乱(wpf MVVM confusion)

编程入门 行业动态 更新时间:2024-10-09 15:17:19
wpf MVVM混乱(wpf MVVM confusion)

我在过去几天一直在关注MVVM,并且我想我会尝试一个简单的例子来更新一个带有时间的文本框。 但是我在缠绕这个问题时遇到了一些麻烦。 我在我的解决方案中有两个项目..一个我正在调用TimeProvider,现在只是返回Datetime事件而另一个叫做E.最后我将使用TimeProvider提供更多信息但我想先了解一些简单的事情。 有人可以告诉我为什么我没有把gui更新。

namespace E.TimeProvider { public interface ITimeSource { void Subscribe(); event Action<Time> TimeArrived; } } namespace E.TimeProvider { public class Time { private DateTime _earthDate; public Time() { } public Time(DateTime earthDate) { this._earthDate = earthDate; } public DateTime EarthDate { get { return _earthDate; } set { _earthDate = value; } } } } namespace E.TimeProvider { public class TimeSource : ITimeSource { private const int TIMER_INTERVAL = 50; public event Action<Time> TimeArrived; private bool subscribe; public TimeSource() { subscribe = false; Thread timeGenerator = new Thread(new ThreadStart(GenerateTimes)); timeGenerator.IsBackground = true; timeGenerator.Priority = ThreadPriority.Normal; timeGenerator.Start(); } public void Subscribe() { if (subscribe) return; subscribe = true; } private void GenerateTimes() { while (true) { GenerateAndPublishTimes(); Thread.Sleep(TIMER_INTERVAL); } } private void GenerateAndPublishTimes() { DateTime earthDate = DateTime.Now; Time time = new Time(earthDate); TimeArrived(time); } } }

然后我有我的项目E xaml

<Window x:Class="E.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="300" Width="200" xmlns:my="clr-namespace:Exiled" WindowStyle="None" WindowStartupLocation="CenterScreen" ResizeMode="NoResize"> <Grid> <my:TimeControl HorizontalAlignment="Left" x:Name="timeControl1" VerticalAlignment="Top" Height="300" Width="200" /> </Grid> </Window> <UserControl x:Class="E.TimeControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="200" Background="Black" Foreground="White"> <Grid> <TextBlock Height="41" HorizontalAlignment="Left" Margin="12,31,0,0" Text="{Binding Path=EarthTime}" VerticalAlignment="Top" Width="176" FontSize="35" TextAlignment="Center" /> </Grid> </UserControl>

其余的

namespace E { public class TimeControlViewModel : DependencyObject { private readonly ITimeSource _source; public ObservableCollection<TimeViewModel> Times { get; set; } public TimeControlViewModel() { this.Times = new ObservableCollection<TimeViewModel>(); } public TimeControlViewModel(ITimeSource source) { this.Times = new ObservableCollection<TimeViewModel>(); _source = source; _source.TimeArrived += new Action<Time>(_source_TimeArrived); } public void Subscribe() { _source.Subscribe(); } void _source_TimeArrived(Time time) { TimeViewModel tvm = new TimeViewModel(); tvm.Time = time; } } } namespace E { class SubscribeCommand { private readonly TimeControlViewModel _vm; public SubscribeCommand(TimeControlViewModel vm) { _vm = vm; } public void Execute(object parameter) { _vm.Subscribe(); } } } namespace E { public class TimeViewModel : DependencyObject { public TimeViewModel() { } public Time Time { set { this.EarthDate = value.EarthDate; } } public DateTime EarthDate { get { return (DateTime)GetValue(DateProperty); } set { SetValue(DateProperty, value); } } // Using a DependencyProperty as the backing store for Date. This enables animation, styling, binding, etc... public static readonly DependencyProperty DateProperty = DependencyProperty.Register("EarthDate", typeof(DateTime), typeof(TimeViewModel), new UIPropertyMetadata(DateTime.Now)); } }

I have been looking at MVVM for the last couple days and thought i would try out a simple example to update a text box with a time. However i'm having a bit of trouble wrapping my head around this. I have a two projects in my Solution.. one i'm calling TimeProvider that right now is just returning Datetime event and another that is called E. Eventually i will use TimeProvider to provide a lot more information but i want to understand something simple first. Can some one please tell me why i'm not geting the gui to update.

namespace E.TimeProvider { public interface ITimeSource { void Subscribe(); event Action<Time> TimeArrived; } } namespace E.TimeProvider { public class Time { private DateTime _earthDate; public Time() { } public Time(DateTime earthDate) { this._earthDate = earthDate; } public DateTime EarthDate { get { return _earthDate; } set { _earthDate = value; } } } } namespace E.TimeProvider { public class TimeSource : ITimeSource { private const int TIMER_INTERVAL = 50; public event Action<Time> TimeArrived; private bool subscribe; public TimeSource() { subscribe = false; Thread timeGenerator = new Thread(new ThreadStart(GenerateTimes)); timeGenerator.IsBackground = true; timeGenerator.Priority = ThreadPriority.Normal; timeGenerator.Start(); } public void Subscribe() { if (subscribe) return; subscribe = true; } private void GenerateTimes() { while (true) { GenerateAndPublishTimes(); Thread.Sleep(TIMER_INTERVAL); } } private void GenerateAndPublishTimes() { DateTime earthDate = DateTime.Now; Time time = new Time(earthDate); TimeArrived(time); } } }

Then i have my project E xaml

<Window x:Class="E.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="300" Width="200" xmlns:my="clr-namespace:Exiled" WindowStyle="None" WindowStartupLocation="CenterScreen" ResizeMode="NoResize"> <Grid> <my:TimeControl HorizontalAlignment="Left" x:Name="timeControl1" VerticalAlignment="Top" Height="300" Width="200" /> </Grid> </Window> <UserControl x:Class="E.TimeControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="200" Background="Black" Foreground="White"> <Grid> <TextBlock Height="41" HorizontalAlignment="Left" Margin="12,31,0,0" Text="{Binding Path=EarthTime}" VerticalAlignment="Top" Width="176" FontSize="35" TextAlignment="Center" /> </Grid> </UserControl>

and the rest

namespace E { public class TimeControlViewModel : DependencyObject { private readonly ITimeSource _source; public ObservableCollection<TimeViewModel> Times { get; set; } public TimeControlViewModel() { this.Times = new ObservableCollection<TimeViewModel>(); } public TimeControlViewModel(ITimeSource source) { this.Times = new ObservableCollection<TimeViewModel>(); _source = source; _source.TimeArrived += new Action<Time>(_source_TimeArrived); } public void Subscribe() { _source.Subscribe(); } void _source_TimeArrived(Time time) { TimeViewModel tvm = new TimeViewModel(); tvm.Time = time; } } } namespace E { class SubscribeCommand { private readonly TimeControlViewModel _vm; public SubscribeCommand(TimeControlViewModel vm) { _vm = vm; } public void Execute(object parameter) { _vm.Subscribe(); } } } namespace E { public class TimeViewModel : DependencyObject { public TimeViewModel() { } public Time Time { set { this.EarthDate = value.EarthDate; } } public DateTime EarthDate { get { return (DateTime)GetValue(DateProperty); } set { SetValue(DateProperty, value); } } // Using a DependencyProperty as the backing store for Date. This enables animation, styling, binding, etc... public static readonly DependencyProperty DateProperty = DependencyProperty.Register("EarthDate", typeof(DateTime), typeof(TimeViewModel), new UIPropertyMetadata(DateTime.Now)); } }

最满意答案

你在这里遇到了一些问题:

您没有看到更新,因为Window或UserControl的DataContext未设置为您创建的TimeViewModel实例。 通常,ViewModel实例不应该是DependencyObjects。 相反,实现INotifyPropertyChanged。 这使他们不再依赖WPF,但仍允许他们与MVVM一起正常工作。

我建议阅读MVVM的详细介绍,比如我在这里写的那篇 。 特别是,您需要了解模板的工作原理和DataContext才能正确使用绑定。

You've got a few issues here:

You're not seeing an update, because the DataContext of your Window or UserControl is not set to the TimeViewModel instance you create. Typically, ViewModel instances should not be DependencyObjects. Instead, implement INotifyPropertyChanged. This keeps them from having a dependency on WPF, but still allows them to work properly with MVVM.

I'd recommend reading through a detailed introduction to MVVM, such as the one I wrote here. In particular, you'll need to understand how templating works and the DataContext in order to use binding properly.

更多推荐

本文发布于:2023-07-17 14:03:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1145661.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:混乱   wpf   MVVM   confusion

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!