2015-09-24 2 views
0

У меня проблема с SelectedItem моего ListBox. Я хочу поставить мой выбранный элемент в выделенном свойстве моего HealthDiseaseViewModel Вот мой ViewModel:MVVM Как поместить ListBox SelectedItem в экземпляр класса из ViewModel

public class HealthDiseaseViewModel : ObservableCollection<HealthDisease> 
{ 
    private string _feedBack; 

    HealthDiseaseDb _db = new HealthDiseaseDb(); 

    public HealthDiseaseRetrieveSingleCommand RetrieveSingleCommand { get; set; } 
    public HealthDiseaseRetrieveManyCommand RetrieveManyCommand { get; set; } 
    public HealthDiseaseUpdateCommand UpdateCommand { get; set; } 

    public HealthDisease Entity { get; set; } 
    public HealthDisease Highlighted { get; set; } 
    public List<HealthDisease> EntityList { get; set; } 

    public HealthDiseaseViewModel() 
    { 
     RetrieveSingleCommand = new HealthDiseaseRetrieveSingleCommand(this); 
     RetrieveManyCommand = new HealthDiseaseRetrieveManyCommand(this);  
     UpdateCommand = new HealthDiseaseUpdateCommand(this);  
     Highlighted = new HealthDisease(); 

     Entity = new HealthDisease(); 
     RetrieveMany(Entity); 
    } 

    #region Methods 

    public void Retrieve(HealthDisease parameters) 
    { 
     Highlighted = _db.Retrieve(parameters);    
    } 

    public void RetrieveMany(HealthDisease parameters) 
    { 
     EntityList = new List<HealthDisease>(); 

     EntityList = _db.RetrieveMany(parameters);  

     IList<HealthDisease> toBeRemoved = Items.ToList(); 

     foreach (var item in toBeRemoved) 
     { 
      Remove(item); 
     } 

     foreach (var item in EntityList) 
     { 
      Add(item); 
     }   
    } 

    public void Insert(HealthDisease entity) 
    { 
     bool doesExist = false; 
     if (_db.Insert(entity, SessionHelper.CurrentUser.Id, ref doesExist)) 
     { 
      _feedBack = "Item Successfully Saved!"; 
      RetrieveMany(new HealthDisease()); 
     } 
     else if (doesExist) 
     { 
      _feedBack = "Item Already Exists!"; 
     } 
     else 
     { 
      _feedBack = "Not All Fields Were Filled-In!"; 
     } 
     MessageBox.Show(_feedBack, "Item Insertion"); 
    } 

    public void Update(HealthDisease entity) 
    { 
     bool doesExist = false; 

     if (_db.Update(entity, SessionHelper.CurrentUser.Id, ref doesExist)) 
     { 
      _feedBack = "Item Successfully Updated!"; 
      RetrieveMany(new HealthDisease()); 
     } 
     else if (doesExist) 
     { 
      _feedBack = "Item Already Exists!"; 
     } 
     else 
     { 
      _feedBack = "Not All Fields Were Filled-In!"; 
     } 
     MessageBox.Show(_feedBack, "Item Edition"); 
    } 

    public void Delete(HealthDisease entity) 
    { 
     var answer = MessageBox.Show(String.Format("Are you sure you want to delete \n{0}?", entity.Name), 
     "Item Deletion", MessageBoxButtons.YesNo); 

     if (answer == DialogResult.No) 
     { 
      return; 
     } 

     if (_db.Delete(entity, SessionHelper.CurrentUser.Id)) 
     { 
      _feedBack = "Item Successfully Deleted!"; 
      RetrieveMany(new HealthDisease()); 
     } 

     MessageBox.Show(_feedBack, "Item Deletion"); 
    } 
    #endregion 
} 

Я связала SelectedItem моего ListBox к Подчеркнута, и я хотел, чтобы Highlighted.Name и Highlighted.Description к TextBlocks, но TextBlocks не отображает SelectedItem. Я могу сделать работу здесь, используя SelectedItem.Name и SelectedItem.Description, но проблема в том, что она автоматически обновляет ListBox, даже если я еще не нажал кнопку сохранения. Использование объекта Highlighted решит это, но теперь я трачу часы разочарования. Вот моя разметка. Я опустил SaveButton, который связан с UpdateCommand от моего ViewModel

<Grid Name="MainGrid" Background="Aqua" MinWidth="500" MinHeight="400" 
     DataContext="{Binding Source={StaticResource HealthViewModel}}"> 

    <StackPanel Orientation="Vertical"> 
     <TextBlock Text="{Binding Path=Highlighted.Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBlock> 
     <ListBox x:Name="EntityListBox" Margin="10,0" Height="380" 
      ItemsSource="{Binding }" 
      DisplayMemberPath="Name" 
      SelectedItem="{Binding Path=Highlighted, Mode=TwoWay, 
            Converter={StaticResource ToHealthDiseaseConverter}, 
            UpdateSourceTrigger=PropertyChanged}" /> 
    </StackPanel> 
</Grid> 
+0

ваш '' ItemsSource' из ListBox' должен быть список HealthDisease. –

+0

, но HealthDiseaseViewModel наследует ObservableCollection, у которого есть INotifyProp ... не будет использовать список HealthDisease, который удалит функцию уведомления? –

ответ

2

Я могу предоставить вам быстрый ответ, но своего рода надеюсь, что вы не будете останавливаться и пытаться выяснить, почему привязки в свойство объекта не буду работать , DependencyProperty привязывается к экземплярам, ​​которые реализуют INotifyPropertyChanged с правильным триггером PropertyChanged. Он не привязывается к «значению» экземпляра. Посмотрите, можете ли вы понять, почему привязка к Highlighted.Name не будет работать.

я создал упрощенный образец для вас

<Window x:Class="WpfTestProj.MainWindow" 
    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:local="clr-namespace:WpfTestProj" 
    mc:Ignorable="d" 
    d:DataContext="{d:DesignInstance Type=local:MainViewModel, IsDesignTimeCreatable=False}" 
    Title="MainWindow" Height="350" Width="525"> 
    <Window.DataContext> 
     <local:MainViewModel/> 
    </Window.DataContext> 
<Grid> 
    <StackPanel Orientation="Vertical"> 
     <StackPanel> 
      <TextBlock Text="{Binding Path=HighlightedName}" /> 
     </StackPanel> 
     <StackPanel> 
      <ListBox x:Name="EntityListBox" Margin="10,0" 
       ItemsSource="{Binding EntityList}" 
       DisplayMemberPath="Name" 
       SelectedItem="{Binding Path=Highlighted, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /> 
     </StackPanel> 
    </StackPanel> 
</Grid> 

public abstract class ViewModelBase : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

    [NotifyPropertyChangedInvocator] 
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) 
    { 
     var handler = PropertyChanged; 
     if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 

public class HealthDisease 
{ 
    public string Name { get; set; } 
} 

public class MainViewModel : ViewModelBase 
{ 
    public ObservableCollection<HealthDisease> EntityList { get; set; } 

    public MainViewModel() 
    { 
     RetrieveMany(); 
    } 

    private void RetrieveMany() 
    { 
     EntityList = new ObservableCollection<HealthDisease> 
     { 
      new HealthDisease {Name = "Disease A"}, 
      new HealthDisease {Name = "Disease B"}, 
      new HealthDisease {Name = "Disease C"} 
     }; 
    } 

    private HealthDisease highlighted; 

    public HealthDisease Highlighted 
    { 
     get { return highlighted; } 
     set 
     { 
      highlighted = value; 
      OnPropertyChanged(); 
      OnPropertyChanged("HighlightedName"); 
     } 
    } 

    public string HighlightedName 
    { 
     get { return Highlighted == null ? string.Empty : Highlighted.Name; } 
    } 
} 
+0

GREAT! Я также получил некоторые сочетания клавиш из вашего примера. Я также не знал, что может быть два OnPropertyChanged() (один с параметрами), который обновляет его в реальном времени. –

+0

Супер полезный образец! Небольшое примечание: ваш текстовый блок в XAML может напрямую связываться с «Path = Highlighted.Name», а затем вам не нужно свойство HighlightedName в виртуальной машине вообще. Я предполагаю, что причина, по которой это не сработала в OP, связана с тем, как его виртуальная машина наследует ObservableCollection (что-то, чего я никогда не делал), вместо того, чтобы внедрять INPC напрямую, как и вы. – kmote

Смежные вопросы