You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于MVVM模式实现选中对象在新UserControl的详情展示

基于MVVM实现单选按钮触发人员详情UserControl的方案

实现思路

  1. 新增人员详情UserControl,布局所有字段的展示控件;
  2. 在ViewModel层添加命令处理单选按钮点击逻辑,同时维护属性控制详情控件的显示状态;
  3. 将单选按钮的选中项绑定到ViewModel的SelectedPersonItem,点击事件绑定到新增命令;
  4. 在主界面通过ContentControl加载详情UserControl,并将其DataContext绑定到选中的人员对象。

步骤1:新增人员详情UserControl(PersonDetailUC.xaml)

<UserControl x:Class="PersonMVVM.PersonDetailUC"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="300">
    <StackPanel Margin="10" Spacing="8">
        <TextBlock Text="人员详情" FontSize="16" FontWeight="Bold"/>
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="ID:" Width="60"/>
            <TextBlock Text="{Binding PersonID}"/>
        </StackPanel>
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="姓名:" Width="60"/>
            <TextBlock Text="{Binding Name}"/>
        </StackPanel>
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="姓氏:" Width="60"/>
            <TextBlock Text="{Binding Surname}"/>
        </StackPanel>
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="年龄:" Width="60"/>
            <TextBlock Text="{Binding PersonAge}"/>
        </StackPanel>
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="地址:" Width="60"/>
            <TextBlock Text="{Binding PersonAddress}"/>
        </StackPanel>
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="部门:" Width="60"/>
            <TextBlock Text="{Binding PersonDepartmentID}"/>
        </StackPanel>
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="组别:" Width="60"/>
            <TextBlock Text="{Binding PersonGroupID}"/>
        </StackPanel>
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="联系方式:" Width="60"/>
            <TextBlock Text="{Binding PersonContact}"/>
        </StackPanel>
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="学历:" Width="60"/>
            <TextBlock Text="{Binding PersonLevelEductationID}"/>
        </StackPanel>
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="分部:" Width="60"/>
            <TextBlock Text="{Binding PersonDivisionID}"/>
        </StackPanel>
    </StackPanel>
</UserControl>

步骤2:完善ViewModelBase,添加命令基类

在ViewModelBase所在文件中添加通用RelayCommand实现:

namespace PersonMVVM
{
    class ViewModelBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public void OnpropertyChanged([CallerMemberName] string propName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
        }
    }

    // 通用命令实现类
    public class RelayCommand : ICommand
    {
        private readonly Action<object> _execute;
        private readonly Func<object, bool> _canExecute;

        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }

        public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null)
        {
            _execute = execute ?? throw new ArgumentNullException(nameof(execute));
            _canExecute = canExecute;
        }

        public bool CanExecute(object parameter)
        {
            return _canExecute == null || _canExecute(parameter);
        }

        public void Execute(object parameter)
        {
            _execute(parameter);
        }
    }
}

步骤3:修改PersonViewModel,添加命令和显示控制属性

namespace PersonMVVM
{
    class PersonViewModel : ViewModelBase
    {
        public ObservableCollection<PersonModel> PersonItems { get; }

        private PersonModel _selectedPersonItem;
        public PersonModel SelectedPersonItem
        {
            get => _selectedPersonItem;
            set { _selectedPersonItem = value; OnpropertyChanged(nameof(SelectedPersonItem)); }
        }

        // 控制详情控件显示状态的属性
        private bool _isDetailVisible;
        public bool IsDetailVisible
        {
            get => _isDetailVisible;
            set { _isDetailVisible = value; OnpropertyChanged(nameof(IsDetailVisible)); }
        }

        // 单选按钮点击命令
        public ICommand ShowDetailCommand { get; }

        private readonly DataRepository dataRepository;
        public PersonViewModel()
        {
            this.PersonItems = new ObservableCollection<PersonModel>();
            this.dataRepository = new DataRepository();
            ShowDetailCommand = new RelayCommand(ExecuteShowDetail);
        }

        private void ExecuteShowDetail(object parameter)
        {
            if (SelectedPersonItem != null)
            {
                IsDetailVisible = true;
            }
        }

        public void Initialize()
        {
            IEnumerable<PersonModel> personModels = this.dataRepository.GetPersonModels();
            foreach (PersonModel personModel in personModels)
            {
                this.PersonItems.Add(personModel);
            }
        }
    }
}

步骤4:修改主窗口,实现单选按钮列表与详情展示

修改MainWindow.xaml,替换原ListBox为单选按钮列表,并添加详情控件容器:

<Window x:Class="PersonMVVM.MainWindow"
        xmlns:local="clr-namespace:PersonMVVM"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">

    <Window.DataContext>
        <local:MainViewModel/>
    </Window.DataContext>

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="200"/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>

        <!-- 单选按钮列表 -->
        <ItemsControl Grid.Column="0" ItemsSource="{Binding PersonViewModel.PersonItems}" Margin="10">
            <ItemsControl.ItemTemplate>
                <DataTemplate DataType="{x:Type local:PersonModel}">
                    <RadioButton Content="{Binding Name}" 
                                 IsChecked="{Binding RelativeSource={RelativeSource AncestorType=ItemsControl}, Path=DataContext.SelectedPersonItem, Converter={local:ObjectEqualsConverter}, ConverterParameter={Binding}}"
                                 Command="{Binding RelativeSource={RelativeSource AncestorType=ItemsControl}, Path=DataContext.ShowDetailCommand}"/>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>

        <!-- 详情控件容器 -->
        <ContentControl Grid.Column="1" Margin="10"
                        Visibility="{Binding PersonViewModel.IsDetailVisible, Converter={x:Static BooleanToVisibilityConverter.Instance}}">
            <local:PersonDetailUC DataContext="{Binding PersonViewModel.SelectedPersonItem}"/>
        </ContentControl>
    </Grid>
</Window>

步骤5:添加对象相等转换器(ObjectEqualsConverter)

用于绑定单选按钮选中状态与ViewModel的选中项:

namespace PersonMVVM
{
    public class ObjectEqualsConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return Equals(value, parameter);
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return (bool)value ? parameter : Binding.DoNothing;
        }
    }
}

原代码保留说明

  • Model、DataRepository、MainViewModel代码无需修改;
  • 原MasterDetailsControl可根据需求保留或移除,本次实现直接在主窗口构建单选列表与详情展示。

内容的提问来源于stack exchange,提问作者mark

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 21:37:31