WPF中的MVVM模式:How to render dynamic controls on the fly in MvvM pattern
2010-07-29 11:09
483 查看
出处: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
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
相关文章推荐
- Notes on how to use Webots, especially how to make a robot fly in the air
- How to add directories to the dynamic library path ld.config on Solaris
- How to set the DefaultButton in a Page Based on ASP.NET Master Page
- How to automatically select all text on focus in WPF TextBox?
- How To Turn Up Logging on the Siebel Web Server Extension in Siebel Versions 7.x and 8.x? [ID 477185
- How to freeze a dynamic aspx page into a static html page (on the server).
- How to freeze a dynamic aspx page into a static html page (on the server).
- TORQUE引擎里如何生成一个在天空中移动的太阳(How to create a sun moving on the sky in the Torque)
- How to grant access to SQL logins on a standby database when the guest user is disabled in SQL Serve
- How to fix the “msvcrt-ruby18.dll is missing from your computer” error message in Ruby on Rails
- How to find child controls that are located in the template of a parent control
- How to invoke the method of managed bean and render view in JSF when we are outside the lifecycle of JSF
- How to freeze a dynamic aspx page into a static html page (on the server).(转:http://codebetter.com/blogs/peter.van.ooijen/archiv
- how to put the text on the left of a radio button in android
- Android开发中的代码关联问题:Failed to create the part'sControls(Unmatched braces in the pattern.)
- how can i change the back color on mouse out to the color specified in gridview
- How to Use the Dynamic Link Library in C++ Linux (C++调用Delphi写的.so文件)
- How to allow a user to click on TextBlocks which return an integer ID in the click handler
- (C#) A demo on how to auto fill out the "account" value in log in web page in "WebBrowser" control.
- how to reference the parent form from the WPF control(Control in ElementHost)