2014-11-06 5 views
0

В настоящее время я пытаюсь понять концепции MVVM. Поэтому я уже читал несколько блогов и смотрел несколько проектов. Тем не менее, я до сих пор не знаю, как применить эту концепцию.Связывание ObservableCollection строк с ListBox в WPF

Прямо сейчас, я пытаюсь привязать ObservableCollection значений String к ListBox, чтобы их значения были перечислены по строкам. Мой ViewModel в настоящее время выглядит следующим образом:

namespace TestApp.ViewModel 
{ 
    class StatusViewModel : NotifyPropertyChanged 
    { 
     private string _newMsg; 
     private readonly ObservableCollection<string> _history = new ObservableCollection<string>(); 

     public string Print 
     { 
      get { return _newMsg; } 
      set 
      { 
       _newMsg = value; 
       RaisePropertyChangedEvent("History"); 
       AddToHistory(_newMsg); 
      } 
     } 

     public IEnumerable<string> History 
     { 
      get { return _history; } 
     } 

     private void AddToHistory(string item) 
     { 
      if (!_history.Contains(item)) 
       _history.Add(item); 
     } 
    } 
} 

namespace TestApp.ViewModel 
{ 
    public class NotifyPropertyChanged : INotifyPropertyChanged 
    { 
     public event PropertyChangedEventHandler PropertyChanged; 

     protected void RaisePropertyChangedEvent(string propertyName) 
     { 
      if (PropertyChanged != null) 
       PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
} 

В представлении, я хочу, чтобы связать ListBox с History. Вот моя XAML:

<UserControl x:Class="TestApp.View.StatusView" 
      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" 
      xmlns:vm="clr-namespace:TestApp.ViewModel" mc:Ignorable="d"> 
    <UserControl.Resources> 
     <vm:StatusView x:Key="statusView"/> 
    </UserControl.Resources> 
    <Grid DataContext="{StaticResource statusView}"> 
     <GroupBox Header="StatusView"> 
      <ListBox x:Name="StatusListBox" ItemsSource="{Binding History, Source={StaticResource statusView}}"/> 
     </GroupBox> 
    </Grid> 
</UserControl> 

Когда я начинаю TestApp, мне нужно, чтобы получить доступ к экземпляру моего StatusViewModel, чтобы добавить строку в моей ObservableCollection. Мне интересно, как это делается:

using TestApp.ViewModel; 

namespace TestApp.Controller 
{ 
    public partial class Startup 
    { 
     private void StartTestApp() 
     { 
      // from where do I get my 'statObj' in order to do: 
      statObj.Print = "something"; 
     } 
    } 
} 

Как связать ObservableCollection строк в моем StatusViewModel объекта к Listbox?

UPDATE:

Спасибо всем за прекрасные комментарии! Теперь я понимаю, что мне нужно иметь экземпляр моего ViewModel, чтобы получить к нему доступ как от . ПросмотриКонтроллер. Тем не менее, я все еще борется с тем, как это сделать правильно. ## Заголовок ##

В настоящее время я начал с создания экземпляра в коде для пользовательского элемента управления. Хотя он работает, мне не нравится, что мне нужно ссылаться на ViewModel в моем представлении. Я подумал, что это весь пункт MVVM не для этого.

Кроме того, мне интересно, как я могу получить доступ к моему недавно созданному статусу StatusViewModel за пределами View, например. в другом пространстве имен с именем Контроллер.

using System.Windows.Controls; 
using TestApp.ViewModel; 

namespace TestApp.View 
{ 
    /// <summary> 
    /// Interaction Logic for StatusView.xaml 
    /// </summary> 
    public partial class StatusView : UserControl 
    { 
     public StatusView() 
     { 
      InitializeComponent(); 

      this.DataContext = new StatusViewModel(); 
     } 

     public TestApp.ViewModel.StatusViewModel State 
     { 
      get { return (DataContext as TestApp.ViewModel.StatusViewModel); } 
     } 
    } 
} 
+1

Binding будет работать над этим экземпляром 'status':' ', и для тестирования вы создаете ** другой экземпляр' Status' ** и меняете 'Print'. Это не те же объекты – dkozl

+0

Это имеет смысл!Но как я могу редактировать существующий объект статуса в методе 'StartTestApp'? Мой метод запуска находится в другом пространстве имен, которое называется 'TestApp.Controller'. – berti

+0

Вам нужно овладеть этим экземпляром. Зависит от вашего дизайна. Некоторые люди используют фреймворки, которые включают локаторы модели просмотра. Обычно я определяю свои виртуальные машины как ресурсы в app.xaml, затем * связываю их друг с другом *, поэтому VM X ссылается на VM Y. Некоторые люди создают их в конструкторе представления, поэтому они ссылаются на него. Как вы хотите. – Will

ответ

0

Изменение XAML к этому:

<UserControl x:Class="TestApp.View.Status" 
     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" 
     xmlns:vm="clr-namespace:TestApp.ViewModel" mc:Ignorable="d"> 
<UserControl.DataContext> 
    <vm:Status /> 
</UserControl.DataContext> 
<Grid> 
    <GroupBox Header="Status"> 
     <ListBox x:Name="StatusListBox" ItemsSource="{Binding History}"/> 
    </GroupBox> 
</Grid> 

И код для доступа к своему viemodel должен содержать следующее:

Status status = DataContext as Status; 
if (status != null) 
    status.Print = "Hello"; 

Тогда это похоже на работу: enter image description here

Если вы хотите получить доступ к экземпляру состояния этого элемента управления пользователя, добавить свойство пользовательского элемента управления:

public TestApp.ViewModel.Status State // Status gives probably naming conflict 
{ 
    get 
    { 
     return (DataContext as TestApp.ViewModel.Status); 
    } 
} 
+0

Спасибо за ваш быстрый ответ! К сожалению, в моем ListBox еще нет сообщения :( – berti

+0

Вы не установили DataContext. О, вы сделали ... извините. – Sjips

+0

Где именно следует добавить 'if (DataContext! = Null) ...'? – berti

0

Попробуйте

public ObservableCollection<string> History 
{ 
    get { return _history; } 
} 
private void AddToHistory(string item) 
{ 
    if (!History.Contains(item)) History.Add(item); 
}