wpf MVVM混乱

时间:2011-04-09 01:08:19

标签: wpf mvvm

过去几天我一直在关注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));
    }
}

2 个答案:

答案 0 :(得分:2)

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

  1. 您没有看到更新,因为您的Window或UserControl的DataContext未设置为您创建的TimeViewModel实例。
  2. 通常,ViewModel实例不应该是DependencyObjects。相反,实现INotifyPropertyChanged。这使他们不再依赖WPF,但仍允许他们与MVVM一起正常工作。
  3. 我建议阅读MVVM的详细介绍,例如one I wrote here。特别是,您需要了解模板的工作原理以及DataContext才能正确使用绑定。

答案 1 :(得分:0)

首先,它看起来像是绑定到EarthTime:

Text="{Binding Path=EarthTime}"

但该属性本身称为EarthDate

public DateTime EarthDate