Wpf学习片段

IRegionManagerIContainerExtension

IRegionManager 是 Prism 框架中用于管理 UI 区域(Regions)的核心接口,它实现了模块化应用中视图(Views)的动态加载、导航和生命周期管理。

IContainerExtension 是依赖注入(DI)容器的抽象接口,而 Resolve<T>() 方法用于从容器中解析指定类型的实例

复制代码
public class u1: UserControl
{
    IRegionManager _regionManager;
    IContainerExtension _container;
    public u1(IContainerExtension container, IRegionManager regionManager)
    {
        _regionManager = regionManager;
        _container = container;
    
    //从容器中解析ListView类型的实例。如果ListView已注册为单例,则返回单例实例;否则返回新实例
         ListView ListView11 =_container.Resolve<ListView>();
         //获取中心显示区域
         IRegion region= _regionManager.Regions["ContentRegion"];
         //为中心显示区域添加视图(ListView11),并为视图分配一个名称"ListView1"
         region.Add(ListView11 , "ListView1");
         //将指定视图(ListView11)设置为区域(region)中的活动视图
         region.Activate(ListView11);

    }

}

u1的xaml中有:

<ContentControl Grid.Column="1" prism:RegionManager.RegionName="ContentRegion" />

......

<dx:DXTabItem Header="名称">

<local:ListView/>//将 ListView 视图嵌入到 DXTabItem 中,作为选项卡页的内容。

</dx:DXTabItem>

其中ListView是自定义的另一个用户控件。

在 Prism 框架中,结合第三方控件库(如 DevExpress 的 DXTabItem)时,可以通过 XAML 直接定义视图(如 ListView)并将其嵌入到选项卡控件中。

region.Activate(view) 方法用于将指定视图(view)设置为区域(IRegion)中的活动视图。

单选框的动态绑定

<StackPanel Margin="20">

<TextBlock Text="组合单选框" FontWeight="Bold"/>

<DockPanel x:Name="GroupRadioButton">

<StackPanel DockPanel.Dock="Left">

<ItemsControl ItemsSource="{Binding RadioButtons}">

<ItemsControl.ItemTemplate>

<DataTemplate>

<RadioButton Content="{Binding SecurityId}"

IsChecked="{Binding IsSelected, Mode=TwoWay}"

GroupName="RadioButtons"

Command="{Binding DataContext.RadioCheckCommand,

RelativeSource={RelativeSource AncestorType=Window}}"

CommandParameter="{Binding}">

</RadioButton>

</DataTemplate>

</ItemsControl.ItemTemplate>

</ItemsControl>

</StackPanel>

<StackPanel DockPanel.Dock="Right"

Orientation="Horizontal"

HorizontalAlignment="Center"

VerticalAlignment="Center">

<TextBlock Text="{Binding SelectedRadioButton.SecurityId, StringFormat='结果:{0}'}" />

</StackPanel>

</DockPanel>

</StackPanel>

复制代码
using Prism.Commands;
using Prism.Mvvm;
using StrategyClient.Models;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;

namespace StrategyClient.ViewModels
{
    class SellStrategyViewModel : BindableBase
    {
        /// <summary>
        /// 当前选择的单选框
        /// </summary>
        private ConfigAccount _selectedRadioButton;
        /// <summary>
        /// 当前选择的单选框
        /// </summary>
        public ConfigAccount SelectedRadioButton
        {
            get => _selectedRadioButton;
            set => SetProperty(ref _selectedRadioButton, value);
        }

        /// <summary>
        /// 需要显示的一组单选框的信息链表
        /// </summary>
        public ObservableCollection<ConfigAccount> RadioButtons { get; } = new ObservableCollection<ConfigAccount>();
        /// <summary>
        /// 绑定命令触发(单选框选择改变时)
        /// </summary>
        public DelegateCommand<ConfigAccount> RadioCheckCommand { get; }
        


        public SellStrategyViewModel()
        {
            // 初始化单选框选项
            RadioButtons.Add(new ConfigAccount { SecurityId = "选项1", IsSelected = false });
            RadioButtons.Add(new ConfigAccount { SecurityId = "选项2", IsSelected = false });
            RadioButtons.Add(new ConfigAccount { SecurityId = "选项3", IsSelected = false });
            // 设置默认选中项
            if (RadioButtons.Count > 0)
            {
                RadioButtons[0].IsSelected = true;
                SelectedRadioButton = RadioButtons[0];
            }
            // 注册命令
            RadioCheckCommand = new DelegateCommand<ConfigAccount>(OnRadioChecked);
        }
        private void OnRadioChecked(ConfigAccount item)
        {
            // 更新选中项
            foreach (var radioButton in RadioButtons)
            {
                radioButton.IsSelected = radioButton == item;
            }
            SelectedRadioButton = item;
        }

      


    }
}

检查UI绑定路径

xmlns:diagnostics="clr-namespace:System.Diagnostics;assembly=WindowsBase"

......

<CheckBox IsChecked="{Binding IsSelectedV, Mode=TwoWay, diagnostics:PresentationTraceSources.TraceLevel=High}"

HorizontalAlignment="Center"

VerticalAlignment="Center"/>
如果直接绑定到 IsSelectedV 属性不起作用,可以尝试使用 CellValue 绑定:
<CheckBox IsChecked="{Binding RowData.Row.IsSelectedV, Mode=TwoWay}"/>

在这种情况下,RowData.Row 通常是指当前行的数据对象。

实现弹窗功能:

//App中注册对话框

containerRegistry.RegisterDialog<View, ViewModel>();
// 显示弹窗

void ShowDialog(string name, IDialogParameters parameters, Action<IDialogResult> callback);

// 显示模态弹窗(阻塞式)

void Show(string name, IDialogParameters parameters, Action<IDialogResult> callback);

主视图的ViewModel:

public ObservableCollection<string> Items

{

get;

set;

} = new ObservableCollection<string>();

/// <summary>

/// 按钮按下弹窗

/// </summary>

private void Button_Click()

{

//传递参数

var parameters = new DialogParameters

{

{ "DataList", Items }

};

//View:视图名,parameters:要传递的参数

_dialogService.ShowDialog("View", parameters, (IDialogResult result) =>

{//弹窗关闭后回调函数

// 从结果中获取数据链表

if (result.Parameters.TryGetValue<ObservableCollection<string>>("DataList", out var dataList))

{

Items = dataList;

}

});

}
// 定义弹窗事件

public class ShowDialogEvent : PubSubEvent<DialogParameters> { }

// 发布弹窗请求

var parameters = new DialogParameters { { "message", "保存成功!" } };

_eventAggregator.GetEvent<ShowDialogEvent>().Publish(parameters);

// 弹窗服务订阅事件并显示弹窗

_eventAggregator.GetEvent<ShowDialogEvent>()

.Subscribe(ShowDialog, ThreadOption.UIThread);

private void ShowDialog(DialogParameters parameters)

{

_dialogService.ShowDialog("MessageDialog", parameters);

}

View视图的ViewModel

class ViewModel : BindableBase, IDialogAware

{

public ObservableCollection<string> Items

{

get => _items;

set => SetProperty(ref _items, value);

}

/// <summary>

/// 对话框事件,传递对话框的结果

/// </summary>

public event Action<IDialogResult> RequestClose;

/// <summary>

/// 关闭对话框时传递参数

/// </summary>

public event Action<IDialogParameters> RequestClosed;

// 对话框标题

public string Title => "弹窗标题";

/// <summary>

/// 允许关闭对话框

/// </summary>

/// <returns></returns>

public bool CanCloseDialog()

{

return true;

}

/// <summary>

/// 关闭对话框时

/// </summary>

public void OnDialogClosed()

{

var resultParameters = new DialogParameters

{

{ "DataList", Items }

};

// 触发请求关闭事件

RequestClosed?.Invoke(resultParameters);

}

/// <summary>

/// 打开对话框时

/// </summary>

/// <param name="parameters"></param>

public void OnDialogOpened(IDialogParameters parameters)

{

if (parameters.TryGetValue<ObservableCollection<SellStrategyModel>>("DataList", out var initialName))

{

Items = initialName;

}

}

}

单选框:

<DockPanel x:Name="GroupRadioButton">

<ItemsControl ItemsSource="{Binding RadioButtons}">

<ItemsControl.ItemsPanel>

<ItemsPanelTemplate>

<WrapPanel Orientation="Horizontal"/>

</ItemsPanelTemplate>

</ItemsControl.ItemsPanel>

<ItemsControl.ItemTemplate>

<DataTemplate>

<RadioButton Content="{Binding Id}"

IsChecked="{Binding IsSelected, Mode=TwoWay}"

GroupName="RadioButtons"

Command="{Binding DataContext.RadioCheckCommand,

RelativeSource={RelativeSource AncestorType=Window}}"

CommandParameter="{Binding}">

</RadioButton>

</DataTemplate>

</ItemsControl.ItemTemplate>

</ItemsControl>

</DockPanel>

viewModel

/// <summary>

/// 当前选择的单选框

/// </summary>

private ConfigAccount _selectedRadioButton;

/// <summary>

/// 当前选择的单选框

/// </summary>

public ConfigAccount SelectedRadioButton

{

get => _selectedRadioButton;

set => SetProperty(ref _selectedRadioButton, value);

}

/// <summary>

/// 需要显示的一组单选框的信息链表

/// </summary>

public ObservableCollection<ConfigAccount> RadioButtons { get; } = new ObservableCollection<ConfigAccount>();

/// <summary>

/// 绑定命令触发(单选框选择改变时)

/// </summary>

public DelegateCommand<ConfigAccount> RadioCheckCommand { get; }

public ViewModel()

{

AddSecurityStrategy();

// 设置默认选中项

if (RadioButtons.Count > 0)

{

RadioButtons[0].IsSelected = true;

SelectedRadioButton = RadioButtons[0];

}

RadioCheckCommand = new DelegateCommand<ConfigAccount>(OnRadioChecked);

}

/// <summary>

/// 单选框按钮选择时触发

/// </summary>

/// <param name="item">选择的单选框对象</param>

private void OnRadioChecked(ConfigAccount item)

{

// 更新选中项

//foreach (var radioButton in RadioButtons)

//{

// radioButton.IsSelected = radioButton == item;

//}

SelectedRadioButton = item;

}

/// <summary>

/// 添加需要显示的单选框按钮

/// </summary>

private void AddSecurityStrategy()

{

string[] addStrategys = System.Configuration.ConfigurationManager.AppSettings["SellStrategy"].ToString().Split('|');

foreach (string addStrategy in addStrategys)

{

RadioButtons.Add(new ConfigAccount() { IsSelected = false, SecurityId = addStrategy });

}

}

动态加载不同模块的 UI

方法一:

1.注册区域

确保 "MainContent" 区域已通过 IRegionManager 注册(通常在 XAML 中声明或代码中动态添加):

_regionManager.Regions.Add("MainContent", new Region());

或者

<!-- 或在 XAML 中声明区域 --> <ContentControl prism:RegionManager.RegionName="MainContent" />

2.App.xaml.cs

//MainView:要加载的视图的名称,MainView1:起的名字

containerRegistry.RegisterForNavigation<MainWindowView, MainWindowViewModel>("MainView1");

//MainView:要加载的视图的名称,没起名字

registry.RegisterForNavigation<MainWindowView, MainWindowViewModel>();

3.点击按钮时实现ViewModel:

//起名字了这里传入起的名字

_regionManager.RequestNavigate("MainContent", "MainView1");

//没起名字,这里传入类名

_regionManager.RequestNavigate("MainContent", "MainWindowView");

//传递参数:

var parameters = new NavigationParameters();

parameters.Add("orderId", 123);

_regionManager.RequestNavigate("MainRegion", "OrderDetailView", parameters);

方法二:

1.注册区域

确保 "MainContent" 区域已通过 IRegionManager 注册(通常在 XAML 中声明或代码中动态添加):

_regionManager.Regions.Add("MainContent", new Region());

或者

<!-- 或在 XAML 中声明区域 --> <ContentControl prism:RegionManager.RegionName="MainContent" />

2.在模块初始化时注册视图到指定区域:

void MainWindow_Loaded(object sender, RoutedEventArgs e)

{//开始的时候MainContent会显示loading视图

_regionManager.RegisterViewWithRegion("MainContent", typeof(loading));

}

3.点击按钮时实现ViewModel:

_regionManager.RequestNavigate("MainContent", "loading");

获取UI界面实例的view Model,调用对应的函数

方法一:

// 获取目标区域

IRegion contentRegion = _regionManager.Regions["MainContent"];

// 获取当前激活的视图

object activeView = contentRegion.ActiveViews.FirstOrDefault();

// 获取视图的 DataContext(即 ViewModel)

var viewModel = activeView.GetType().GetProperty("DataContext")?.GetValue(activeView) as DownLoadViewModel;

//调用视图方法改变UI内文字

viewModel?.testc();

方法二:

//注册为单例

registry.RegisterSingleton<DownLoadViewModel>();

// 直接解析 ViewModel 实例

var viewMode2 = _container.Resolve<DownLoadViewModel>();

viewMode2?.testc();

注册服务

方法 用途 生命周期控制
RegisterForNavigation<TView>() 注册视图到导航系统,自动绑定 ViewModel(通过命名约定) 默认瞬态(每次导航创建新实例)
RegisterSingleton<T>() 注册类型为单例,全局唯一实例 单例
RegisterForNavigation<TView, TViewModel>() 显式指定视图和 ViewModel 的绑定关系 可自定义(结合其他注册方法)
Register<TInterface, TImplementation>() 注册接口到具体实现 默认瞬态
RegisterInstance<T>(T instance) 注册已创建的实例为单例 单例

//举例

registry.RegisterForNavigation<DownLoadView, DownLoadViewModel>("DownLoad1");

registry.RegisterForNavigation<MainWindowView, MainWindowViewModel>();

registry.RegisterSingleton<DownLoadViewModel>();

registry.RegisterForNavigation<DownLoadView>("downLoad");

registry.RegisterForNavigation<loading>();

containerRegistry.Register<IDownLoadService, DownLoadService>();

var downloadService = new DownLoadService(); containerRegistry.RegisterInstance<IDownLoadService>(downloadService);

管理区域和视图:

方法 用途 特点
RegisterViewWithRegion 静态注册视图到区域,自动加载 适用于固定视图,初始化时自动加载
RequestNavigate 动态导航到视图,支持参数和回调 适用于按需加载的视图,支持导航逻辑
IRegion.Add / IRegion.Remove 手动添加或移除视图 适用于精细控制视图的显示/隐藏
IRegion.Activate / IRegion.Deactivate 激活或停用视图 适用于切换视图的可见性
IRegion.NavigationService 通过导航服务实现复杂导航逻辑 适用于需要自定义导航流程的场景

//举例

protected override void OnInitialized(IContainerProvider containerProvider)

{

var regionManager = containerProvider.Resolve<IRegionManager>();

// 将 OrderListView 注册到 MainRegion,视图会在区域初始化时自动加载 regionManager.RegisterViewWithRegion("MainRegion", typeof(OrderListView));

}

_regionManager.RequestNavigate("MainContent", "loading");

var region = _regionManager.Regions["MainRegion"];

var view = _container.Resolve<OrderListView>();

region.Add(view); region.Activate(view); // 激活视图

var region = _regionManager.Regions["MainRegion"];

var view = region.Views.FirstOrDefault(v => v is OrderListView); if (view != null)

{ region.Remove(view); }

var region = _regionManager.Regions["MainRegion"];

var view = region.Views.FirstOrDefault(v => v is OrderListView); if (view != null)

{

region.Activate(view); // 激活视图

// region.Deactivate(view); // 停用视图

}

INavigationAware:

INavigationAware 是 Prism 框架中用于处理导航生命周期事件的核心接口。它允许 ViewModel 在导航过程中响应以下三个关键事件:

  • 导航到当前视图时(OnNavigatedTo
  • 从当前视图导航离开时(OnNavigatedFrom
  • 导航确认阶段(IsNavigationTarget,用于决定是否复用现有 ViewModel 实例)

通过实现 INavigationAware,可以精细控制 ViewModel 在导航过程中的行为,例如初始化数据、清理资源或决定是否复用实例。

  • INavigationAware 是 Prism 中管理导航生命周期的核心接口。
  • 通过实现 IsNavigationTargetOnNavigatedToOnNavigatedFrom,可以精细控制 ViewModel 在导航过程中的行为。
  • 适用于需要初始化数据、清理资源或决定是否复用实例的场景。
  • 合理使用导航参数(NavigationParameters)可以传递上下文数据。

区域上下文

是一种用于在区域(IRegion)和其宿主控件(如 ContentControlItemsControl 等)之间传递上下文数据的机制。它允许开发者在区域中共享数据,而无需直接依赖视图或视图模型,从而提升代码的解耦性和灵活性。

// 获取区域并设置上下文 var region = _regionManager.Regions["MainRegion"]; region.Context = new AppContext { UserId = "123", Role = "Admin" };//AppContext:自定义Mode

App.config用法

App.config代码:

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

<startup>

<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />

</startup>

<appSettings>

<add key="keyName" value="valueName"/>

<add key="keyName2" value="valueName2"/>

<add key="keyName3" value="valueName3"/>

</appSettings>

</configuration>
string settingValue = System.Configuration.ConfigurationManager.AppSettings["keyName"];

相关推荐
西岸行者5 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
悠哉悠哉愿意5 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
别催小唐敲代码5 天前
嵌入式学习路线
学习
毛小茛5 天前
计算机系统概论——校验码
学习
babe小鑫5 天前
大专经济信息管理专业学习数据分析的必要性
学习·数据挖掘·数据分析
winfreedoms5 天前
ROS2知识大白话
笔记·学习·ros2
在这habit之下5 天前
Linux Virtual Server(LVS)学习总结
linux·学习·lvs
我想我不够好。5 天前
2026.2.25监控学习
学习
im_AMBER5 天前
Leetcode 127 删除有序数组中的重复项 | 删除有序数组中的重复项 II
数据结构·学习·算法·leetcode
CodeJourney_J5 天前
从“Hello World“ 开始 C++
c语言·c++·学习