WPF应用程序(.NET Core) 列表数据编辑(弹出层形式 反填+修改)
WPF应用程序(.NET Core) 列表数据编辑(弹出层形式反填+修改)
一、列表操作列中加入编辑按钮--并绑定事件
1、 .xaml文件设计

1 <!-- CommandParameter="{Binding}" 代表把当前行的对象作为参数传递 --> 2 <!-- RelativeSource进行绑定,这种办法的意思是指当前元素和绑定源的位置关系 --> 3 <!-- AncestorType指定绑定源为某个父元素 --> 4 <Button 5 Command="{Binding Path=DataContext.EditOpenCommand, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" 6 CommandParameter="{Binding}" 7 Content="编辑" />
以下可借助参考别人的,不全一样 : Prism之对话服务(DialogService)
2、创建用于在点击列表编辑按钮后触发实现显示dialog接口 (接口名字后面改成了IDialogShow)

1 /// <summary> 2 /// 弹出层接口, 用于弹出 弹出层 3 /// </summary> 4 public interface IDialogHostService 5 { 6 /// <summary> 7 /// 弹出弹出层窗口 8 /// </summary> 9 /// <param name="name">弹出层页面的名</param> 10 /// <param name="parameters">给弹出层的页面传递的参数</param> 11 /// <param name="dialogHostName">弹出层的控件的Identifier属性的值 默认使用Home.xaml视图里的 DialogHost 控件</param> 12 /// <returns></returns> 13 Task<IDialogResult> ShowDialog(string name, IDialogParameters parameters, string dialogHostName = "RootDialog"); 14 }
3、 .cs触发事件编辑(笔记涉及IDialogHostServer接口名字后面改成了IDialogShow)

1 private readonly IDialogHostService _IDialogHostService; 2 /// <summary> 3 /// 列表操作列编辑委托 4 /// </summary> 5 /// 编辑按钮 6 public DelegateCommand<LoginUser> EditOpenCommand { get; private set; } 7 public UserManagerViewModel(IDialogHostService _IDialogHostServices, IEventAggregator aggregators, IRegionManager regionManager) : base(aggregators) 8 { 9 this.regionManager = regionManager; 10 EditOpenCommand = new DelegateCommand<LoginUser>(OpenUpdDialog); 11 //依赖注入dialog服务,用于弹出弹出层 12 _IDialogHostService = _IDialogHostServices; 13 } 14 /// <summary> 15 /// 打开编辑页页dialog的方法 16 /// </summary> 17 /// <param name="LoginUser">传递的参数</param> 18 public async void OpenUpdDialog(LoginUser u) 19 { 20 //存放dialog初始的数据--反填 21 DialogParameters param = new DialogParameters(); 22 if (u != null) 23 { 24 param.Add("UserValue", u); 25 } 26 //弹出用户修改dialog UserUpd--修改页名(.xaml文件名) 27 var dialogResult = await _IDialogHostService.ShowDialog("UserUpd", param); 28 }
4、创建在弹出diaolg后,弹出层中的点击事件的对应实现接口

1 /// <summary> 2 /// 定义弹出窗口实现方法的接口 3 /// </summary> 4 public interface IDialogOperate 5 { 6 7 /// <summary> 8 /// 窗体名称 9 /// </summary> 10 string WindowName { get; set; } 11 12 /// <summary> 13 /// 打开过程中执行 14 /// </summary> 15 /// <param name="parameters">参数</param> 16 void OnDialogOpend(IDialogParameters parameters); 17 18 /// <summary> 19 /// 确定命令 20 /// </summary> 21 DelegateCommand SaveCommand { get; set; } 22 23 /// <summary> 24 /// 取消命令 25 /// </summary> 26 DelegateCommand CancelCommand { get; set; } 27 }
5、创建DialogShow.cs类继承并实现上述IDialogShow接口类方法

1 public class DialogShow : DialogService, IDialogShow 2 { 3 //prism Ioc 容器 4 private readonly IContainerExtension containerExtension; 5 6 /// <summary> 7 /// 注入ioc容器 8 /// </summary> 9 /// <param name="containerExtension"></param> 10 public DialogShow(IContainerExtension containerExtension) : base(containerExtension) 11 { 12 this.containerExtension = containerExtension; 13 } 14 /// <summary> 15 /// 弹出弹出层窗口 16 /// </summary> 17 /// <param name="name">弹出层页面的类名</param> 18 /// <param name="parameters">给弹出层的页面传递的参数</param> 19 /// <param name="dialogHostName">弹出层的 Identifier属性的key</param> 20 /// <returns></returns> 21 /// <exception cref="NullReferenceException"></exception> 22 23 public async Task<IDialogResult> ShowDialog(string name, IDialogParameters parameters, string dialogHostName = "RootDialog") 24 { 25 if (parameters == null) 26 parameters = new DialogParameters(); 27 28 //在App.xaml中注入的IOC(prism自带的IOC) 29 //从容器当中取出弹出窗口的实例根据弹出层的类名 根据名称获取视图 30 var content = containerExtension.Resolve<object>(name); 31 //判断是否弹出层这个容器注入到了IOC中 有没有APP。xaml注册 32 if (content == null) 33 { 34 throw new NullReferenceException("IOC容器中没有执行弹出层要弹出的窗体"); 35 } 36 //验证实例的有效性 验证弹出层类型是否是WPF的元素 必须是FrameworkElement类型 37 //是则把他赋值给dialogContent 38 if (!(content is FrameworkElement dialogContent)) 39 throw new NullReferenceException("弹出层的 content 必须是 FrameworkElement 类型"); 40 41 //是则把他转化(赋值)为view 42 if (dialogContent is FrameworkElement view && view.DataContext is null && ViewModelLocator.GetAutoWireViewModel(view) is null) 43 ViewModelLocator.SetAutoWireViewModel(view, true); 44 45 //如果没有继承IDialogShow接口 46 if (!(dialogContent.DataContext is IDialogOperate viewModel)) 47 throw new NullReferenceException("弹出层 ViewModel 必须继承接口 IDialogOpenWindow "); 48 49 //赋值dialog名 50 viewModel.WindowName = dialogHostName; 51 52 //一个委托 53 DialogOpenedEventHandler eventHandler = (sender, eventArgs) => 54 { 55 if (viewModel is IDialogOperate aware) 56 { 57 //调用打开过程中执行方法 58 aware.OnDialogOpend(parameters); 59 } 60 eventArgs.Session.UpdateContent(content); 61 }; 62 return (IDialogResult)await DialogHost.Show(dialogContent, viewModel.WindowName, eventHandler); 63 64 } 65 }
5、App.Xaml文件prism IOC容器注册
6、创建弹出层页面窗体(右键添加用户控件)和其ViewModel类 App.xaml文件中映射建立联系
7、设计xaml页面布局(新建一个弹出层页面)

<UserControl x:Class="GroupThreeObject02WindosWPF.View.SystemBase.User.UserUpd" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:Validation="clr-namespace:GroupThreeObject02WindosWPF.Common.Validation" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:i="http://schemas.microsoft.com/xaml/behaviors" xmlns:local="clr-namespace:GroupThreeObject02WindosWPF.View.SystemBase.User" xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:md="http://materialdesigninxaml.net/winfx/xaml/themes" xmlns:passWord="clr-namespace:GroupThreeObject02WindosWPF.Common.Extensions" d:DesignHeight="450" d:DesignWidth="800" mc:Ignorable="d"> <!-- 申明一个用户控件资源 --> <UserControl.Resources /> <md:DialogHost x:Name="DialogHost" DialogTheme="Inherit" Identifier="Root"> <Grid Background="White"> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition /> <RowDefinition /> <RowDefinition /> </Grid.RowDefinitions> <TextBlock Grid.Row="0" Padding="20,10" FontSize="20" FontWeight="Bold" Text="{Binding DialogTitleName}" /> <DockPanel Grid.Row="1" LastChildFill="False"> <StackPanel Margin="0,10,10,10" DockPanel.Dock="Top" Orientation="Horizontal"> <StackPanel.Style> <!-- 申明一个触发器, 触发器关联的空间类型是 StackPanel --> <Style TargetType="StackPanel"> <Style.Triggers> <!-- 触发器为data触发器 如果 IsUpdate 是true --> <DataTrigger Binding="{Binding IsUpdate}" Value="true"> <!-- StackPanel 显示 --> <Setter Property="Visibility" Value="Visible" /> </DataTrigger> <!-- 触发器为data触发器 如果 IsUpdate 是false --> <DataTrigger Binding="{Binding IsUpdate}" Value="false"> <!-- StackPanel 不显示 --> <Setter Property="Visibility" Value="Collapsed" /> </DataTrigger> </Style.Triggers> </Style> </StackPanel.Style> <TextBox Width="200" Margin="0,0,10,0" VerticalAlignment="Center" materialDesign:HintAssist.Hint="用户名" Style="{StaticResource MaterialDesignFilledTextBox}"> <TextBox.Text> <Binding Path="user_name" UpdateSourceTrigger="PropertyChanged"> <Binding.ValidationRules> <Validation:NotEmptyValidationRule ValidatesOnTargetUpdated="True" /> </Binding.ValidationRules> </Binding> </TextBox.Text> </TextBox> <TextBox Width="200" VerticalAlignment="Center" materialDesign:HintAssist.Hint="用户全名" Style="{StaticResource MaterialDesignFilledTextBox}" Text="{Binding user_full_name}" /> </StackPanel> <StackPanel Margin="0,10,10,10" DockPanel.Dock="Top" Orientation="Horizontal"> <StackPanel.Style> <!-- 申明一个触发器, 触发器关联的空间类型是 StackPanel --> <Style TargetType="StackPanel"> <Style.Triggers> <!-- 触发器为data触发器 如果 IsUpdate 是true --> <DataTrigger Binding="{Binding IsUpdatePwd}" Value="true"> <!-- StackPanel 显示 --> <Setter Property="Visibility" Value="Visible" /> </DataTrigger> <!-- 触发器为data触发器 如果 IsUpdate 是false --> <DataTrigger Binding="{Binding IsUpdatePwd}" Value="false"> <!-- StackPanel 不显示 --> <Setter Property="Visibility" Value="Collapsed" /> </DataTrigger> </Style.Triggers> </Style> </StackPanel.Style> <PasswordBox Width="200" Margin="0,0,10,0" VerticalAlignment="Center" materialDesign:HintAssist.Hint="密码" passWord:PassWordExtension.Password="{Binding pwd, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource MaterialDesignFilledPasswordBox}"> <i:Interaction.Behaviors> <passWord:PasswordBehavior /> </i:Interaction.Behaviors> </PasswordBox> <PasswordBox Width="200" VerticalAlignment="Center" materialDesign:HintAssist.Hint="验证密码" passWord:PassWordExtension.Password="{Binding VPassWord, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource MaterialDesignFilledPasswordBox}"> <i:Interaction.Behaviors> <passWord:PasswordBehavior /> </i:Interaction.Behaviors> </PasswordBox> </StackPanel> </DockPanel> <StackPanel Grid.Row="2" Margin="10" HorizontalAlignment="Right" Orientation="Horizontal"> <Button Margin="0,0,10,0" Command="{Binding CancelCommand}" Content="取消" Style="{StaticResource MaterialDesignOutlinedButton}" /> <Button Command="{Binding SaveCommand}" Content="确定" /> </StackPanel> </Grid> </md:DialogHost> </UserControl>
8、编写.CS文件实现对应功能

using GroupThreeObject02DBModel; using GroupThreeObject02ViewModel.Common; using GroupThreeObject02WindosWPF.Common; using GroupThreeObject02WindosWPF.Common.Extensions; using GroupThreeObject02WindosWPF.Common.MyDialog; using GroupThreeObject02WindosWPF.Service.Login; using MaterialDesignThemes.Wpf; using Prism.Commands; using Prism.Events; using Prism.Regions; using Prism.Services.Dialogs; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace GroupThreeObject02WindosWPF.View.SystemBase.User { internal class UserUpdViewModel : BaseViewModel, IDialogOperate { private readonly LoginUserInfoService _LoginUserInfoService; private readonly IRegionManager regionManager; public string WindowName { get; set; } //依赖注入 public UserUpdViewModel(IEventAggregator aggregators, LoginUserInfoService _LoginUserInfoServices, IRegionManager regionManager) : base(aggregators) { _LoginUserInfoService = _LoginUserInfoServices; SaveCommand = new DelegateCommand(Save); CancelCommand = new DelegateCommand(Cancel); //regionManager = regionManager;//跳转页面 } private bool _isUpdate; /// <summary> /// 控制修改用户名那个容器StackPanel的触发器 控制StackPanel容器是否显示 true是显示 false 是不显示 /// </summary> public bool IsUpdate { get { return _isUpdate; } } private bool _IsUpdatePwd; /// <summary> /// 控制修改密码容器StackPanel的触发器 控制StackPanel容器是否显示 true是显示 false 是不显示 /// </summary> public bool IsUpdatePwd { get { return _IsUpdatePwd; } } /// <summary> /// 弹出层dialog文本标题 /// </summary> private string _DialogTitleName; public string DialogTitleName { get { return _DialogTitleName; } } public string userName; public string password; public string _user_full_name; /// <summary> /// 用户名--通过wpf页面获取用户名--双向绑定 /// </summary> public string user_name { get { return userName; } set { userName = value; RaisePropertyChanged(); //双向绑定通知 继承BindableBase基类 } } /// <summary> /// 用户全名 /// </summary> public string user_full_name { get { return _user_full_name; } set { _user_full_name = value; RaisePropertyChanged(); } } /// <summary> /// 密码 /// </summary> public string pwd { get { return password; } set { password = value; RaisePropertyChanged(); } } public string _vPassWord; /// <summary> /// 验证密码 /// </summary> public string VPassWord { get => _vPassWord; set { _vPassWord = value; RaisePropertyChanged(); } } //获取diaLog传过来的对象--最后用于修改 private LoginUser adminUser; /// <summary> /// 打开弹出层页面执行的方法--赋值,判断打开哪个页面 /// </summary> /// <param name="parameters">传递用户对象</param> public void OnDialogOpend(IDialogParameters parameters) { //根据弹出层传过来的值的key值进行判断当下是编辑的用户信息还是密码 if (parameters.ContainsKey("UserValue")) { //取出来传的值,实现反填 adminUser = parameters.GetValue<LoginUser>("UserValue"); userName = adminUser.user_name; _user_full_name = adminUser.user_full_name; _isUpdate = true; _IsUpdatePwd = false; _DialogTitleName = "信息修改"; } //修改密码 if (parameters.ContainsKey("PwdValue")) { //取出来传的值,实现反填 adminUser = parameters.GetValue<LoginUser>("PwdValue"); password = adminUser.pwd; _isUpdate = false; _IsUpdatePwd = true; _DialogTitleName = "密码修改"; } } /// <summary> /// 保存事件委托 /// </summary> public DelegateCommand SaveCommand { get; set; } /// <summary> /// 取消事件委托 /// </summary> public DelegateCommand CancelCommand { get; set; } /// <summary> /// 取消,关闭弹出窗 /// </summary> private void Cancel() { if (DialogHost.IsDialogOpen(WindowName)) DialogHost.Close(WindowName, new DialogResult(ButtonResult.No)); //取消返回NO告诉操作结束 } /// <summary> /// 确定保存 /// </summary> private async void Save() { //if (string.IsNullOrWhiteSpace(Model.Title) || // string.IsNullOrWhiteSpace(model.Content)) return; if (DialogHost.IsDialogOpen(WindowName)) { try { WaitFor(true); await Task.Delay(2000); //DialogParameters param = new DialogParameters(); //param.Add("Value", AdminUser); //调用api修改保存 if (_isUpdate) { //代表修改用户信息 LoginUser l = new LoginUser() { Lid = adminUser.Lid, user_name = user_name, user_full_name = user_full_name }; var res = _LoginUserInfoService.UpdUser(l); aggregator.SendMessage(res.mess); DialogHost.Close(WindowName); // 默认跳转到欢迎起始页 //regionManager.Regions[PrismAreaName.MainViewRegionName].RequestNavigate("UserManager"); } if (_IsUpdatePwd) { //代表修改密码 LoginUser l = new LoginUser() { Lid = adminUser.Lid, pwd = pwd }; var res = _LoginUserInfoService.UpdPwd(l); aggregator.SendMessage(res.mess); DialogHost.Close(WindowName); //刷新显示页 } //DialogHost.Close(WindowName, new DialogResult(ButtonResult.OK, param)); } catch { } finally { WaitFor(false); } } } } }
8、编写过程遇到的问题
8-1:忘记是怎么解决了
8-2:
解决:
效果:---此效果也借助了触发器实现的
本文来自博客园,作者:じ逐梦,转载请注明原文链接:https://www.cnblogs.com/ZhuMeng-Chao/p/16410852.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?