我有一个我正在研究与股票有关的应用程序。
它有点像Josh Smith的MVVM演示应用程序,有一些附加功能。
我有一个名为ShortQuote.cs的数据模型
它有一个viewmodel ShortQuoteViewModel
,但现在没有使用ShortQuoteViewModel。
我有一个ShortQuoteRepository
,它创建了一个从XML数据文件中获取的ShortQuote
类型的对象列表。当用户单击主窗口左窗格上的命令时,ShortQuoteRepository
列表将显示在选项卡中。
我在MainWindow
上有一个组合框,里面有一个自动收报机符号列表。当用户选择其中一个股票代码时,我想从ShortQuoteRepository中获取一个StockQuote对象(如果它存在于该股票代码中),并在MainWindow
视图顶部的TextBlocks中显示它的内容。
我能让这个工作的唯一方法是在MainWindowViewModel
上公开“新”属性,它们是ShortQuote数据模型上属性的镜像,然后一旦我从中获取ShortQuote
对象ShortQuoteRepository我将MainWindowViewModel
的“new”属性设置为等于检索到的对象的属性。我将TextBlock绑定到MainWindowViewModel
的“新”属性,它可以工作。
我觉得这是一个“黑客”,并且有一个“更好”的方法来实现这一点,而不必在MainWindowViewModel上创建“新”属性,并请求有关如何完成此操作的一些指导和建议只需使用XAML或XAML和MainWindowViewModel
代码的组合,就可以更简单的方式创建这些“新”属性。
任何人都可以帮助我吗?
答案 0 :(得分:5)
还可以使ShortQuote成为ViewModel(或者至少使用ObservableObject,如果您使用的是MVVM Light)。然后,您可以将SelectedItem
绑定到viewmodel上的ShortQuote
属性(将其标记为TwoWay)。然后,您的视图可以根据需要引用SelectedItem
。
将此添加到ShortQuoteViewModel.cs
private ShortQuote _selectedQuote;
public ShortQuote SelectedQuote
{
get { return _selectedQuote; }
set
{
if(value != _selectedQuote)
{
_selectedQuote = value;
RaisePropertyChanged("SelectedQuote");
}
}
}
XAML:
<ListBox ItemsSource="{Binding Quotes}" SelectedItem={Binding SelectedQuote, Mode=TwoWay}"/>
<TextBlock Text="{Binding SelectedQuote.Ticker}"/>
您还必须更改ShortQuote
类(可能在ShortQuote.cs
中)以实现INotifyPropertyChanged
,方法是明确实施INPC,或者继承自ViewModel或ObservableObject
(如果使用MVVM Light。你没有指定,但它很流行,如果你不使用它,你应该考虑这样做。)
编辑以下是一份工作样本:
XAML:
<Window x:Class="StockQuoteExample.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="24"/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock>
<Run Text="Company Name: "/>
<Run Text="{Binding SelectedTicker.Ticker}"/>
<Run Text=" Symbol: "/>
<Run Text="{Binding SelectedTicker.StockName}"/>
<Run Text=" Tick Price: "/>
<Run Text="{Binding SelectedTicker.TickPrice}"/>
</TextBlock>
<ListBox Grid.Row="1" Margin="10" ItemsSource="{Binding StockQuotes}" SelectedItem="{Binding SelectedTicker, Mode=TwoWay}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Width="120" Text="{Binding Ticker}"/>
<TextBlock Width="120" Margin="5,0,5,0" Text="{Binding StockName}"/>
<TextBlock Width="120" Text="{Binding TickPrice}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Window>
代码隐藏:
using System.Windows;
using StockQuoteExample.ViewModel;
namespace StockQuoteExample
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new StockQuoteViewModel();
}
}
}
视图模型:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using StockQuoteExample.DataModel;
namespace StockQuoteExample.ViewModel
{
class StockQuoteViewModel : INotifyPropertyChanged
{
public ObservableCollection<StockQuote> StockQuotes { get; set; }
private StockQuote _selectedTicker;
public StockQuote SelectedTicker
{
get { return _selectedTicker; }
set
{
if (value != _selectedTicker)
{
_selectedTicker = value;
OnPropertyChanged("SelectedTicker");
}
}
}
public StockQuoteViewModel()
{
StockQuotes = new ObservableCollection<StockQuote>()
{
new StockQuote() {StockName = "Microsoft", TickPrice = 150m, Ticker = "MSFT"},
new StockQuote() {StockName = "Apple", TickPrice = 600m, Ticker = "AAPL"}
};
}
public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
数据模型:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
namespace StockQuoteExample.DataModel
{
public class StockQuote : INotifyPropertyChanged
{
private string _ticker;
public string Ticker
{
get { return _ticker; }
set
{
if (value != _ticker)
{
_ticker = value;
OnPropertyChanged("Ticker");
}
}
}
private string _stockName;
public string StockName
{
get { return _stockName; }
set
{
if (value != _stockName)
{
_stockName = value;
OnPropertyChanged("StockName");
}
}
}
private decimal _tickPrice;
public decimal TickPrice
{
get { return _tickPrice; }
set
{
if (value != _tickPrice)
{
_tickPrice = value;
OnPropertyChanged("TickPrice");
}
}
}
public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
}