WPF中的MVVM模式:How to render dynamic controls on the fly in MvvM pattern

出处:http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/1be16a18-ab9c-4381-952a-4aa642f159e1

 

For MVVM, we usually use ViewModel to get raw data from data source and create public properties for raw data to enable vm binding to update the view; I’d create new controls on the fly in view code behind (for example, in MainWindow class) because it is a view thing.  Let’s take a look at the MVVM example below to see how to use vm binding to update view, the WatchListViewModel gets raw Quote date from QuoteSource, and it has public properties Quotes and LastSymbol to enable the vm binding for Quote data.

Example:

<Window x:Class="MVVMSample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <TextBlock Text="Quote Name: "/>
        <TextBox Text="{Binding Path=Symbol, UpdateSourceTrigger=PropertyChanged}" Grid.Column="1" Background="LightBlue"/>
        <TextBlock Grid.Row="1" Text="Last Quote Name: "/>
        <TextBlock Text="{Binding Path=LastSymbol}" Grid.Row="1" Grid.Column="1" Background="LightCoral"/>
        <Button Grid.Row="2" Content="Subscribe" Command="{Binding SubscribeCommand}" />
        <ListView Grid.Row="3" Grid.ColumnSpan="2" Background="LightYellow" ItemsSource="{Binding Quotes}">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="Symbol" DisplayMemberBinding="{Binding Path=Symbol}" Width="80" />
                    <GridViewColumn Header="Price" DisplayMemberBinding="{Binding Path=Price}" Width="80"/>
                </GridView>
            </ListView.View>
        </ListView>
    </Grid>
</Window>

using System;
using System.Collections.ObjectModel;
using System.Threading;
using System.Windows;
using System.Windows.Input;
using System.Windows.Threading;

namespace MVVMSample
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new WatchListViewModel(new QuoteSource());
        }
    }
    public class WatchListViewModel : DependencyObject
    {
        private ISource source;
        private Dispatcher currentDispatcher = Dispatcher.CurrentDispatcher;
        public WatchListViewModel(ISource source)
        {
            this.source = source;
            this.Quotes = new ObservableCollection<Quote>();
            this.source.QuoteArrived += new Action<Quote>(source_QuoteArrived);
            this.SubscribeCommand = new SubscribeCommnand(this);
        }
        void source_QuoteArrived(Quote quote)
        {
            Action action = () => Quotes.Add(quote);
            currentDispatcher.BeginInvoke(action);
        }
        public string Symbol { set; get; }
        public string LastSymbol
        {
            get { return (string)GetValue(LastSymbolProperty); }
            set { SetValue(LastSymbolProperty, value); }
        }
        public static readonly DependencyProperty LastSymbolProperty =
            DependencyProperty.Register("LastSymbol", typeof(string), typeof(WatchListViewModel), new UIPropertyMetadata(""));
        public ObservableCollection<Quote> Quotes { set; get; }
        public ICommand SubscribeCommand { set; get; }
        public void Subscribe()
        {
            source.Subscribe(Symbol);
            LastSymbol = Symbol;
        }
    }
    public class SubscribeCommnand : ICommand
    {
        private WatchListViewModel vm;
        public SubscribeCommnand(WatchListViewModel vm) { this.vm = vm; }
        public bool CanExecute(object parameter) { return !String.IsNullOrEmpty(vm.Symbol); }
        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }
        public void Execute(object parameter) { vm.Subscribe(); }
    }
    public interface ISource
    {
        void Subscribe(string symbol);
        event Action<Quote> QuoteArrived;
    }
    public class Quote
    {
        public string Symbol { set; get; }
        public double Price { set; get; }
    }
    public class QuoteSource : ISource
    {
        static double price = 10;
        private string symbol;
        public void Subscribe(string symbol)
        {
            this.symbol = symbol;
            Thread workerThread = new Thread(new ThreadStart(GenerateQuote)) { IsBackground = true, Priority = ThreadPriority.Normal };
            workerThread.Start();
        }
        private void GenerateQuote()
        {
            Thread.Sleep(TimeSpan.FromSeconds(1)); // Time consuming work
            if (!String.IsNullOrEmpty(symbol) && QuoteArrived != null)
                QuoteArrived(new Quote { Symbol = symbol, Price = price++ });
        }
        public event Action<Quote> QuoteArrived;
    }
}


William

posted on 2010-07-29 11:09  I过T  阅读(466)  评论(0编辑  收藏  举报

导航