Ищете руководство с привязкой текстового блока MVVM на mainviewmodel - PullRequest
2 голосов
/ 26 марта 2012

У меня есть приложение, над которым я работаю, касающееся акций.

Это похоже на демонстрационное приложение Джоша Смита MVVM с некоторыми дополнениями.

У меня есть модель данных с именем ShortQuote.cs, у которой есть модель представления ShortQuoteViewModel, но ShortQuoteViewModel сейчас не используется.

У меня есть ShortQuoteRepository, который создает список объектов типа ShortQuote, полученный из файла данных XML.Список ShortQuoteRepository появляется на вкладке, когда пользователь нажимает на команду на левой панели главного окна.

У меня на MainWindow есть поле со списком символов тикеров.Когда пользователь выбирает один из этих символов тикера, я хочу получить один из объектов StockQuote из ShortQuoteRepository (если он существует для этого тикера) и отобразить его содержимое в TextBlocks вверху представления MainWindow.

Единственный способ заставить это работать - это выставить «новые» свойства в MainWindowViewModel, которые являются зеркалами свойств в модели данных ShortQuote, затем, как только я получу объект ShortQuote из ShortQuoteRepositoryЯ установил «новые» свойства MainWindowViewModel равными свойствам извлеченного объекта.Я привязываю TextBlock к «новым» свойствам MainWindowViewModel, и это работает.

Я чувствую, что это «взлом» и что есть «лучший» способ сделать это, не имеячтобы создать «новые» свойства в MainWindowViewModel, и я запрашиваю некоторые рекомендации и предложения о том, как сделать это более простым способом с помощью только XAML или комбинации кода XAML и MainWindowViewModel, который не требует создания этих «новых»свойства.

Кто-нибудь может мне помочь?

1 Ответ

5 голосов
/ 26 марта 2012

Также сделайте свой ShortQuote ViewModel (или, по крайней мере, ObservableObject, если вы используете MVVM Light). Затем вы можете привязать SelectedItem к свойству 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>

Codebehind:

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();
        }
    }
}

ViewModel:

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;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...