c# - MVVM 如何将 ListBox SelectedItem 放入 ViewModel 中的类的实例中

标签 c# wpf xaml mvvm listbox

我的 ListBox 的 SelectedItem 有问题。我想把我选择的项目放在我的 HealthDiseaseViewModel 的 Highlighted 属性中
这是我的 View 模型:

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   
}

我将我的 ListBox 的 SelectedItem 绑定(bind)到 Highlighted 并且我想要 Highlighted.Name 和 Highlighted.Description 到 TextBlocks,但是 TextBlocks 不显示 SelectedItem。我可以通过使用 SelectedItem.Name 和 SelectedItem.Description 来解决这里的问题,但问题是即使我还没有点击保存按钮,它也会自动更新 ListBox。使用突出显示的对象可以解决这个问题,但我现在已经花了好几个小时感到沮丧。
这是我的标记。我从 ViewModel 中省略了绑定(bind)到 UpdateCommand 的 SaveButton
<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>

最佳答案

我可以为您提供一个快速的答案,但希望您不要停在这里并试图找出为什么绑定(bind)到对象的属性中不起作用。 DependencyProperty 绑定(bind)到使用适当的 raise PropertyChanged 触发器实现 INotifyPropertyChanged 的​​实例。它不绑定(bind)到实例的“值”。看看你是否能弄清楚为什么绑定(bind)到 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; }
    }
}

关于c# - MVVM 如何将 ListBox SelectedItem 放入 ViewModel 中的类的实例中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32765202/

相关文章:

c# - 如何使用 WinForms PropertyGrid 编辑字符串列表?

c# - 任务的延续(由 async/await 构建)在 WPF 应用程序的主线程上运行,但在控制台应用程序的子线程上运行

c# - 使用 Phone Accent Brush 时按 Windows Phone 按钮不按任何按钮

c# - 如何找到在多边形内放置标签的最佳位置

c# - DP 更改值后启用并聚焦已禁用的控件

c# - WPF:如何为内容更改创建路由事件?

visual-studio - VS2010 只需 5 秒即可轻松打开任何 XAML 文件(!)

c# - 如何在 C# 中检查 datarow 行中是否为 null

c# - 参数类型 'object' 不可分配给参数类型 'System.Windows.Forms.Control

c# - 我正在构建的应用程序是否可以使用现有的数据层?