【发布时间】:2020-12-27 20:09:08
【问题描述】:
简而言之:我有一个 ListView,当我选择 ListView 的一个项目时,该项目应显示并在详细 UserControl 中进行编辑。
我有一个窗口 (ViewMain) 和一个用户控件 (UserControlEmployees),它有一个 ListView 和另一个用户控件 (UserControlEmployeeDetails)。 ListView 的项目由第三个 UserControl (UserControlEmployee) 显示。 UserControlEmployees 有两个依赖属性:一个 ObservableCollection (Employees) 和一个单个 Employee (SelectedEmployee)。 ViewModel 将 ObservableCollection 传递给 UserControlEmployees。 UserControlEmployees 然后将Employees 传递给ListView。 ListView 的 SelectedItem 绑定到 SelectedEmployee。
SelectedEmployee 也应该绑定到 UserControlEmployeeDetails。所以我尝试将 ViewModelEmployeeDetail 和 ListView 的 SelectedItem 绑定到同一个依赖属性。
我猜这个问题在 UserControlEmployees 中: 我的想法是 control.ControlEmployeesListView.SelectedItem = e.NewValue as Employee;将 SelectedItem 绑定到 SelectedEmployee。但这不起作用,我不知道我还能如何绑定它。通常我会在 XAML 中做类似的事情,但在这种情况下我无权访问它。
编辑 我注意到我忘记将 ListView SelectedItem 设置为 Binding。
<ListView
x:Name="ControlEmployeesListView"
Grid.Row="0"
SelectedItem="{Binding Mode=TwoWay}">
我解决了这个问题,但现在我得到了这个异常:
System.Windows.Markup.XamlParseException: ''在 'System.Windows.Data.Binding' 上提供值引发了异常。'行号“26”和行位置“17”。'
内部异常 InvalidOperationException:双向绑定需要 Path 或 XPath。
/编辑 UserControlEmployees.xaml
<UserControl
x:Class="TestNestedUserControls.View.UserControls.UserControlEmployees"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:uc="clr-namespace:TestNestedUserControls.View.UserControls"
d:DesignHeight="25"
d:DesignWidth="300"
mc:Ignorable="d">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!-- ListView -->
<ListView Grid.Row="0">
<ListView x:Name="ControlEmployeesListView" Grid.Row="0">
<ListView.ItemTemplate>
<DataTemplate>
<uc:UserControlEmployeeListItem EmployeeListItem="{Binding}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ListView>
<!-- Details -->
<uc:UserControlEmployeeDetails x:Name="ControlUserControlEmployeeDetails" Grid.Row="1" />
<!-- SelectedEmployee="{Binding}" -->
</Grid>
</UserControl>
这就是它的 UserControlEmployees.xaml.cs 中的代码
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using TestNestedUserControls.Model;
namespace TestNestedUserControls.View.UserControls
{
/// <summary>
/// Interaction logic for UserControlEmployees.xaml
/// </summary>
public partial class UserControlEmployees : UserControl, INotifyPropertyChanged
{
public UserControlEmployees()
{
InitializeComponent();
}
// List Items
public ObservableCollection<Employee> Employees
{
get { return (ObservableCollection<Employee>)GetValue(EmployeesProperty); }
set
{
SetValue(EmployeesProperty, value);
NotifyPropertyChanged();
}
}
public static readonly DependencyProperty EmployeesProperty =
DependencyProperty.Register(nameof(Employees), typeof(ObservableCollection<Employee>), typeof(UserControlEmployees), new PropertyMetadata(default, SetNew));
private static void SetNew(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = d as UserControlEmployees;
if (control != null)
{
control.ControlEmployeesListView.ItemsSource = e.NewValue as ObservableCollection<Employee>;
}
}
//Selected Item
public Employee SelectedEmployee
{
get { return (Employee)GetValue(EmployeeProperty); }
set
{
SetValue(EmployeeProperty, value);
NotifyPropertyChanged();
}
}
public static readonly DependencyProperty EmployeeProperty =
DependencyProperty.Register(nameof(SelectedEmployee), typeof(Employee), typeof(UserControlEmployees), new PropertyMetadata(default, SetNewSelected));
private static void SetNewSelected(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = d as UserControlEmployees;
if (control != null)
{
control.ControlUserControlEmployeeDetails.EmployeeDetail = e.NewValue as Employee;
control.ControlEmployeesListView.SelectedItem = e.NewValue as Employee;
}
}
#region INotifyPropertyChanged ⬇️
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion ⬆️
}
}
【问题讨论】:
-
请只发布代码的相关部分
-
当然,我不确定。
-
您的数据结构看起来很简单:员工列表,以及查看所选员工详细信息的能力。所以:一个包含
Employee列表和当前Employee的文件的包装器。这使您在视图端拥有一个ListView,在 VM 端拥有一个ObservableCollection。 -
抱歉,P.Manthe,我不确定我是否可以跟上。
标签: c# wpf xaml mvvm user-controls