Prism技巧
Prism 8.0
Prism一般架构
using Prism.DryIoc;
using DryIoc.Microsoft.DependencyInjection;
using HandyControl;
using Microsoft.Extensions.Http;
protected override Window CreateShell()
{
return Container.Resolve<MainWindow>();
}
protected override IContainerExtension CreateContainerExtension()
{
var services = MicrosoftDependencyInjection();
var extension = base.CreateContainerExtension() as DryIocContainerExtension;
return new DryIocContainerExtension(extension.Instance.WithDependencyInjectionAdapter(services));
}
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterForNavigation<Views.DataGridDemo>();
containerRegistry.RegisterDialog<Views.Common.InfoDialog>();
containerRegistry.RegisterDialog<Views.Common.ErrorDialog>();
containerRegistry.RegisterDialog<Views.Common.PrismDialog>();
}
/// <summary>
/// 使用微软官方依赖注入
/// </summary>
/// <returns></returns>
private IServiceCollection MicrosoftDependencyInjection()
{
return new ServiceCollection()
.AddHttpClient()
.AddLogging(loggingBuilder =>
{
// TODO
});
}
xmlns:prism="http://prismlibrary.com/"
xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
xmlns:cvt="clr-namespace:Module.Project1.Common.Converter"
<UserControl.Resources>
<cvt:TypeConv x:Key="TypeConverter"/>
</UserControl.Resources>
<ContentControl prism:RegionManager.RegionName="{x:Static base:RegionNames.MainRegion}"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch"/>
导航
using Prism.Commands;
using Prism.Mvvm;
using Prism.Regions;
using System.Threading.Tasks;
public class DemoViewModel : BindableBase, INavigationAware
{
#region Field
private readonly IDependencyService _dependencyService;
#endregion
#region Property
#endregion
#region Command
#endregion
#region Execute
#endregion
#region Method
#endregion
public DemoViewModel(IDependencyService dependencyService)
{
_dependencyService = dependencyService;
}
#region INavigationAware
public bool IsNavigationTarget(NavigationContext navigationContext)
{
return true;
}
public void OnNavigatedTo(NavigationContext navigationContext)
{
// 导航进来时调用
var guid = navigationContext.Parameters.GetValue<string>("Guid");
var temp = navigationContext.Parameters.GetValue<string>("Parameter2");
_dependencyService.TryApiMethod(() => GetInfoAsync());
}
public void OnNavigatedFrom(NavigationContext navigationContext)
{
// 导航离开当前页,跳转到其他页时调用
}
#endregion
}
其中,DependencyService是一般常用依赖注入项的集合,便于统一调用。
View事件 ViewModel响应
UserControl
using Microsoft.Xaml.Behaviors.Wpf;
<b:Interaction.Triggers>
<b:EventTrigger EventName="Loaded">
<b:InvokeCommandAction Command="{Binding LoadedCommand}"/>
</b:EventTrigger>
</b:Interaction.Triggers>
/// <summary>
/// 当前属性集合实体对象
/// </summary>
public DtoEntity PropSetEntity { get; set; }
public DelegateCommand LoadedCommand => new DelegateCommand(ExecuteLoadedCommand); // cmd
void ExecuteLoadedCommand()
{
_dependencyService.RegionManager.RequestNavigate(RegionNames.MainRegion, nameof(Views.DataGridDemo));
}
private readonly DependencyService _dependencyService;
public MainWindowViewModel(DependencyService dependencyService)
{
_dependencyService = dependencyService;
}
ChildDialog
// father view
<DataGridTemplateColumn Header="内容" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Button Content="详情" Foreground="Blue"
Command="{Binding DataContext.DetailInfoCommand, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=DataGrid}}"
CommandParameter="{Binding ElementName=ucChildDlg}"/>
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<base:DialogForm x:Name="ucChildDlg"/>
// father viewmodel
using Prism.Services.Dialogs;
public DelegateCommand<object> GetDataCommand { get; private set; }
DetailInfoCommand = new DelegateCommand<object>(DetailInfo_Click);
private void DetailInfo_Click(object obj)
{
if (obj is DialogForm childDlg && PropSetEntity.SelectedItem is DemoDto dto)
{
var parameters = new DialogParameters
{
{ "dto", dto}
};
childDlg.Show(new DemoDetailInfo(), parameters, () => { });
childDlg.FormMargin = new Thickness(20, 20, 20, 20);
}
}
// child viewmodel
public class DemoDetailInfoViewModel : BindableBase, IDemoDialogAware
{
public void OnDialogOpened(IDialogParameters parameters)
{
var dto = parameters.GetValue<DemoDto>("dto");
}
}
DataGrid
<DataGrid Grid.Row="0" x:Name="DataGrid1" ItemsSource="{Binding ItemsSourceData}" SelectedItem="{Binding SelectedItem}">
<b:Interaction.Triggers>
<b:EventTrigger EventName="SelectionChanged">
<b:InvokeCommandAction Command="{Binding SelectionChangedCommand}"
CommandParameter="{Binding SelectedItem, ElementName=DataGrid1}"/>
</b:EventTrigger>
<b:EventTrigger EventName="BeginningEdit">
<b:InvokeCommandAction Command="{Binding DataGridBeginningEditCommand}"
PassEventArgsToCommand="True"/>
</b:EventTrigger>
<b:EventTrigger EventName="CellEditEnding">
<b:InvokeCommandAction Command="{Binding DataGridCellEditEndingCommand}"
PassEventArgsToCommand="True"/>
</b:EventTrigger>
</b:Interaction.Triggers>
<DataGrid.Columns>
<DataGridTextColumn Width="*" Header="列头提示2" Binding="{Binding PropertyName1}" IsReadOnly="True"/>
<DataGridComboBoxColumn Width="*" Header="列头提示1" SelectedValueBinding="{Binding PropertyName2}"
SelectedValuePath="Key" DisplayMemberPath="Value">
<DataGridComboBoxColumn.ElementStyle>
<Style TargetType="ComboBox">
<Setter Property="ItemsSource" Value="{Binding DataContext.PropertyName2Source, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" />
<Setter Property="SelectedValue" Value="{Binding Key, Converter={StaticResource propertyName2Converter}}"/>
</Style>
</DataGridComboBoxColumn.ElementStyle>
<DataGridComboBoxColumn.EditingElementStyle>
<Style TargetType="ComboBox">
<Setter Property="ItemsSource" Value="{Binding DataContext.PropertyName2Source, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" />
<Setter Property="SelectedValue" Value="{Binding Value}"/>
</Style>
</DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>
<DataGridTemplateColumn Header="操作" Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Content="DetailInfo" Command="{Binding DataContext.DetailInfoCommand, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=DataGrid}}" CommandParameter="{Binding ElementName=ucChildDlg}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
<base:DialogForm x:Name="ucChildDlg"/>
PUBLIC ObservableCollection<DataGridRowDto> ItemsSourceData { get; private set; }
private object _selectedItem;
public object SelectedItem
{
get { return _selectedItem; }
set { SetProperty(ref _selectedItem, value); }
}
ItemsSourceData通过Clear、AddRange等操作更新UI数据;
注意:绑定的是公共属性;
using System.Windows.Controls;
public DelegateCommand<object> SelectionChangedCommand { get; private set; }
public DelegateCommand<object> DataGridBeginningEditCommand { get; private set; }
public DelegateCommand<object> DataGridCellEditEndingCommand { get; private set; }
public DelegateCommand<object> DetailInfoCommand { get; private set; }
SelectionChangedCommand = new DelegateCommand<object>(DataGrid_SelectionChanged);
DataGridBeginningEditCommand = new DelegateCommand<object>(DataGrid_BeginningEdit);
DataGridCellEditEndingCommand = new DelegateCommand<object>(DataGridCell_EditEnding);
DetailInfoCommand = new DelegateCommand<object>(DetailInfo_Click);
private void DetailInfo_Click(object obj)
{
if (obj is DialogForm childDlg && SelectedItem is DataGridRowDto dto)
{
var parameters = new DialogParameters();
parameters.Add("dto", dto);
childDlg.Show(new ChildView(), parameters, () => { });
childDlg.FormMargin = new System.Windows.Thickness(200, 100, 200, 100);
}
}
private void DataGrid_SelectionChanged(object parameter)
{
if(parameter != null){}
}
private string _preValue = string.Empty;
private void DataGrid_BeginningEdit(object parameter)
{
if (parameter is DataGridBeginningEditEventArgs e)
{
if (e.Column.Header.Equals("列头提示1"))
{
_preValue = (e.Column.GetCellContent(e.Row) as ComboBox).SelectedValue.ToString();
}
}
}
private void DataGridCell_EditEnding(object parameter)
{
if (parameter is DataGridCellEditEndingEventArgs e)
{
string newValue = string.Empty;
if (e.Column.Header.Equals("列头提示1"))
{
newValue = (e.EditingElement as ComboBox).SelectedValue.ToString();
if (_preValue != newValue
&& int.TryParse(newValue, out int type)
&& e.Row.DataContext is ExampleEto item)
{
// TODO
}
}
}
}
其中,CommandParameter的优先级高于PassEventArgsToCommand,若两者同时出现,传递的参数是CommandParameter的值。
ComboBox
<ComboBox x:Name="ComboBox1" SelectedValuePath="Key" DisplayMemberPath="Value"
ItemsSource="{Binding DtoSource}" SelectedItem="{Binding SelectedDto}"
SelectedValue="{Binding DtoSelectedValue}" SelectedIndex="{Binding DtoIndex}">
<b:Interaction.Triggers>
<b:EventTrigger EventName="SelectionChanged">
<b:InvokeCommandAction Command="{Binding ComboBoxDtoSelectionChangedCommand}" PassEventArgsToCommand="True" />
</b:EventTrigger>
</b:Interaction.Triggers>
</ComboBox>
using Prism.Mvvm;
private string _dtoSelectedValue;
public string DtoSelectedValue
{
get => _dtoSelectedValue;
set => SetProperty(ref _dtoSelectedValue, value);
}
public DelegateCommand ComboBoxDtoSelectionChangedCommand { get; private set; }
ComboBoxDtoSelectionChangedCommand = new DelegateCommand<object>(ComboBoxDto_SelectionChanged);
private void ComboBoxDto_SelectionChanged(object parameter)
{
if (parameter is SelectionChangedEventArgs e && e.OriginalSource is ComboBox cmb) { }
}
CheckBox
<CheckBox x:Name="CheckBox1" Tag="{x:Static comm:ParaControlType.XXX}">
<b:Interaction.Triggers>
<b:EventTrigger EventName="Checked">
<b:InvokeCommandAction Command="{Binding CheckBoxItemCheckedCommand}" PassEventArgsToCommand="True"/>
</b:EventTrigger>
<b:EventTrigger EventName="Unchecked">
<b:InvokeCommandAction Command="{Binding CheckBoxItemUncheckedCommand}" CommandParameter="{Binding ElementName=CheckBox1}"/>
</b:EventTrigger>
</b:Interaction.Triggers>
</CheckBox>
<CheckBox x:Name="chk_XXX" IsChecked="{Binding XXX, Converter={StaticResource StringToBoolConverter}}" Tag="XXX"
IsEnabled="{Binding EditingItem.XXXIsEnable}">
<b:Interaction.Triggers>
<b:EventTrigger EventName="Checked">
<b:InvokeCommandAction Command="{Binding CheckBoxValueCheckedCommand}" PassEventArgsToCommand="True"/>
</b:EventTrigger>
<b:EventTrigger EventName="Unchecked">
<b:InvokeCommandAction Command="{Binding CheckBoxValueUncheckedCommand}" PassEventArgsToCommand="True"/>
</b:EventTrigger>
</b:Interaction.Triggers>
</CheckBox>
public DelegateCommand<object> CheckBoxValueCheckedCommand { get; private set; }
CheckBoxValueCheckedCommand = new DelegateCommand<object>(CheckBoxValue_Checked);
private void CheckBoxValue_Checked(object parameter)
{
if (parameter is RoutedEventArgs e && e.OriginalSource is CheckBox ckb) { }
}
ListBox + CheckBox
<ListBox Grid.Row="5" x:Name="ListBox1" Margin="2" ItemsSource="{Binding ListBox1Source}">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding PropertyName}" IsChecked="{Binding IsCheck}" x:Name="CheckBox2" Tag="{Binding}">
<b:Interaction.Triggers>
<b:EventTrigger EventName="Checked">
<b:InvokeCommandAction Command="{Binding DataContext.ListBox1CheckedCommand, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl}}"
PassEventArgsToCommand="True"/>
</b:EventTrigger>
<b:EventTrigger EventName="Unchecked">
<b:InvokeCommandAction Command="{Binding DataContext.ListBox1UncheckedCommand, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl}}"
CommandParameter="{Binding ElementName=CheckBox2, Path=Tag}"/>
</b:EventTrigger>
</b:Interaction.Triggers>
</CheckBox>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
TextBox
<TextBox x:Name="TextBox1" Text="{Binding EditingItem.XXX}" Tag="XXX" IsEnabled="{Binding EditingItem.XXXIsEnable}">
<b:Interaction.Triggers>
<b:EventTrigger EventName="TextChanged">
<b:InvokeCommandAction Command="{Binding TextBox1TextChangedCommand}"/>
</b:EventTrigger>
<b:EventTrigger EventName="KeyDown">
<b:InvokeCommandAction Command="{Binding TextBox1KeyDownCommand}" PassEventArgsToCommand="True"/>
</b:EventTrigger>
</b:Interaction.Triggers>
</TextBox>
private void TextBox1_KeyDown(object parameter)
{
if (parameter is KeyEventArgs e && e.Key == System.Windows.Input.Key.Enter && e.OriginalSource is TextBox txt)
{
// TODO
}
}
RadioCheck
可参考WPF 属性值绑定、转换
Button
<Button Content="测试" x:Name="ButtonTest" Command="{Binding ButtonTestCommand}" CommandParameter="{Binding RelativeSource={x:Static RelativeSource.Self}}" />
DelegateCommand<Button> ButtonQueryCommand;
ButtonQueryCommand = new DelegateCommand<Button>(Test_Click);
Grid 鼠标响应
<Grid Background="Transparent">
<Grid.InputBindings>
<MouseBinding MouseAction="LeftClick"
Command="{Binding DataContext.NavigatePatrolCarCommand, RelativeSource={RelativeSource AncestorType=UserControl}}"
CommandParameter="{Binding Guid}"/>
</Grid.InputBindings>
</Grid>
TreeView
<TreeView Name="TreeView1" ItemTemplate="{DynamicResource ItemNode}"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
VirtualizingPanel.IsVirtualizing="True"
VirtualizingStackPanel.VirtualizationMode ="Standard">
<b:Interaction.Triggers>
<b:EventTrigger EventName="SelectedItemChanged">
<b:InvokeCommandAction Command="{Binding TreeView1SelectedItemChangedCommand}"
CommandParameter="{Binding RelativeSource={x:Static RelativeSource.Self}}"/>
</b:EventTrigger>
</b:Interaction.Triggers>
</TreeView>
TabControl
<TabControl prism:RegionManager.RegionName="{x:Static local:RegionNames.AdvancedSetup}">
<TabControl.ItemContainerStyle>
<Style TargetType="TabItem">
<Setter Property="Visibility" Value="{Binding DataContext.IsAvailable, Converter={coverters:BooleanToVisibilityConverter}}"/>
<Setter Property="Header" Value="{Binding DataContext.Name}"/>
</Style>
</TabControl.ItemContainerStyle>
</TabControl>
regionManager.RegisterViewWithRegion(RegionNames.AdvancedSetup, tabView1);
regionManager.RegisterViewWithRegion(RegionNames.AdvancedSetup, tabView2);
tabView1ViewModel中需要包含属性Name、IsAvailable等信息。
PagerSimple
xmlns:ws="https://wessoncontrol.com/WessonControl"
<ws:PagerSimple HorizontalAlignment="Center" PageSize="{Binding SelectedItem.PagerSize, Mode=TwoWay}"
CurrentPageCount="{Binding SelectedItem.CurrentPageCount, Mode=TwoWay}"
IsPagerInitialized="{Binding SelectedItem.IsPagerInitialized, Mode=TwoWay}">
<b:Interaction.Triggers>
<b:EventTrigger EventName="PageChangedEvent">
<b:InvokeCommandAction Command="{Binding GetDataCommand}" PassEventArgsToCommand="True"/>
</b:EventTrigger>
</b:Interaction.Triggers>
</ws:PagerSimple>
// 1
public DelegateCommand<object> GetDataCommand { get; private set; }
// 2
GetDataCommand = new DelegateCommand<object>(GetData_Click);
// 3
private void GetData_Click(object parameter)
{
if (parameter is PagerSimpleEventArgs e)
{
LocalParking.TryApiMethod(() => DataBindAsync(e.PageIndex, e.PageSize));
}
}
RaiseCanExecuteChanged
using System.Reflection;
private void RaiseCanExecuteChangedAll()
{
var props = new List<PropertyInfo>(this.GetType().GetProperties());
foreach (PropertyInfo prop in props)
{
if (prop.PropertyType.IsSubclassOf(typeof(DelegateCommandBase)))
{
var cmd = (DelegateCommandBase)prop.GetValue(this, null);
cmd.RaiseCanExecuteChanged();
}
}
}
ViewModel找到View控件
var region = _regionManager.Regions[RegionNames.RegionName1];
if (region != null && region.Views.FirstOrDefault() is Views.View1 view)
{
_dataGrid1 = view.DataGrid1;
}
Prism + DialogInfo
public IDialogService DialogService { get; }
public static void PrismShowInfo(string message)
{
var cts = new CancellationTokenSource(5000);
cts.Token.Register(() =>
{
Application.Current.Dispatcher.Invoke(() =>
{
EventAggregator.GetEvent<LoadingFinishedEvent>().Publish();
});
});
Task.Run(() =>
{
Application.Current.Dispatcher.Invoke(() =>
{
var parameters = new DialogParameters($"title=提示:&message={message}&canOperate=Collapsed")
{
{ "cts", cts }
};
DialogService.ShowDialog("MessageDialog", parameters, null);
});
}, cts.Token);
}
public static void PrismShowConfirm(string message, Action<IDialogResult> callback = null)
{
var cts = new CancellationTokenSource(5000);
cts.Token.Register(() =>
{
Application.Current.Dispatcher.Invoke(() =>
{
EventAggregator.GetEvent<LoadingFinishedEvent>().Publish();
});
});
Task.Run(() =>
{
Application.Current.Dispatcher.Invoke(() =>
{
var parameters = new DialogParameters($"title=提示:&message={message}&canOperate=Visible")
{
{ "cts", cts }
};
DialogService.ShowDialog("MessageDialog", parameters, callback);
});
}, cts.Token);
}
Prism + DialogForm蒙版形式
xaml
<UserControl x:Class="WessonControll.Views.PrismDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True">
<prism:Dialog.WindowStyle>
<Style TargetType="Window">
<Setter Property="prism:Dialog.WindowStartupLocation" Value="CenterOwner" />
<Setter Property="ShowInTaskbar" Value="False" />
<Setter Property="SizeToContent" Value="WidthAndHeight" />
<Setter Property="WindowStyle" Value="None" />
<Setter Property="AllowsTransparency" Value="True" />
<Setter Property="Background" Value="Transparent" />
</Style>
</prism:Dialog.WindowStyle>
<Grid>
<Border
Width="{Binding DialogWidth}"
Height="{Binding DialogHeight}"
Background="{StaticResource RegionBrush}"
BorderBrush="{StaticResource PanelBorderBrush}"
BorderThickness="1"
CornerRadius="4">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid Margin="24,20,24,0">
<TextBlock
FontSize="16"
Foreground="{DynamicResource DefaultForegroundBrush}"
Text="{Binding Title}" />
<Button
Width="12"
Height="12"
Margin="4"
HorizontalAlignment="Right"
BorderThickness="0"
Command="{Binding CloseCommand}"
Style="{StaticResource ButtonDefault}">
<Button.Background>
<ImageBrush ImageSource="{DynamicResource MessageDialogSource}" />
</Button.Background>
</Button>
</Grid>
<ContentControl Grid.Row="1" x:Name="contentControl" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
</Grid>
</Border>
</Grid>
</UserControl>
cs
using Prism.Regions;
using System.Windows;
using System.Windows.Controls;
using WessonControll.ViewModels;
namespace WessonControll.Views
{
/// <summary>
/// Interaction logic for PrismDialog
/// </summary>
public partial class PrismDialog : UserControl
{
public PrismDialog(IRegionManager regionManager)
{
InitializeComponent();
var regionName = System.Guid.NewGuid().ToString();
if (regionManager != null && !regionManager.Regions.ContainsRegionWithName(regionName))
{
SetRegionManager(regionManager, contentControl, regionName);
}
if (this.DataContext is PrismDialogViewModel vm)
{
vm.RegionName = regionName;
}
}
private void SetRegionManager(IRegionManager regionManager, DependencyObject regionTarget, string regionName)
{
RegionManager.SetRegionName(regionTarget, regionName);
RegionManager.SetRegionManager(regionTarget, regionManager);
}
}
}
viewmodel
using Prism.Commands;
using Prism.Events;
using Prism.Ioc;
using Prism.Mvvm;
using Prism.Regions;
using Prism.Services.Dialogs;
using System;
using System.Linq;
namespace WessonControll.ViewModels
{
public class PrismDialogViewModel : BindableBase, IDialogAware
{
#region Fields
private readonly DependencyService _dependencyService;
private readonly IContainerExtension _container;
/// <summary>
/// 可否关闭弹框,默认true可以关闭
/// </summary>
private bool _bCanClosed;
private readonly string _message;
#endregion
#region Properties
public string RegionName { get; set; }
private string _tittle = "页面标题";
public string Title
{
get => _tittle;
set => SetProperty(ref _tittle, value);
}
private double _dialogWidth;
public double DialogWidth
{
get => _dialogWidth;
set => SetProperty(ref _dialogWidth, value);
}
private double _dialogHeight;
public double DialogHeight
{
get => _dialogHeight;
set => SetProperty(ref _dialogHeight, value);
}
private bool _closeVisible;
/// <summary>
/// 关闭按钮的可见性
/// </summary>
public bool CloseVisible
{
get => _closeVisible;
set => SetProperty(ref _closeVisible, value);
}
#endregion
#region Commands
public DelegateCommand CloseCommand => new DelegateCommand(ExecuteCloseCommand);
#endregion
public PrismDialogViewModel(DependencyService dependencyService, IContainerExtension container)
{
_dependencyService = dependencyService;
_container = container;
dependencyService.EventAggregator.GetEvent<DialogCanCloseEvent>().Subscribe(DialogCanClose_Event);
dependencyService.EventAggregator.GetEvent<DialogCloseEvent>().Subscribe(DialogClose_Event);
DialogWidth = 1000;
DialogHeight = 820;
_bCanClosed = true;
_message = "有新的操作未保存,是否关闭?";
}
#region Execute
private void DialogCanClose_Event(bool bClose)
{
_bCanClosed = bClose;
}
private void DialogClose_Event(DialogParameters obj)
{
DialogResult result = new DialogResult(ButtonResult.Ignore, obj);
Close(result);
}
private void ExecuteCloseCommand()
{
Close(new DialogResult(ButtonResult.Ignore));
}
private void Close(DialogResult result)
{
if (_bCanClosed)
{
_dependencyService.RegionManager.Regions.Remove(RegionName);
RequestClose?.Invoke(result);
}
else
{
_dependencyService.DialogService.ShowMessage("提示:", _message, System.Windows.Visibility.Visible, callback =>
{
if (callback.Result != ButtonResult.OK)
{
return;
}
_dependencyService.RegionManager.Regions.Remove(RegionName);
RequestClose?.Invoke(result);
});
}
}
#endregion
#region Interface IDialogAware
public event Action<IDialogResult> RequestClose;
public bool CanCloseDialog()
{
return true;
}
public void OnDialogClosed()
{
_dependencyService.EventAggregator.GetEvent<DialogCanCloseEvent>().Unsubscribe(DialogCanClose_Event);
_dependencyService.EventAggregator.GetEvent<DialogCloseEvent>().Unsubscribe(DialogClose_Event);
}
public void OnDialogOpened(IDialogParameters parameters)
{
Title = parameters.GetValue<string>("title");
DialogWidth = parameters.GetValue<double>("width");
DialogHeight = parameters.GetValue<double>("height");
CloseVisible = parameters.GetValue<bool>("close");
var type = parameters.GetValue<Type>("type");
var source = type.FullName;
var region = _dependencyService.RegionManager.Regions[RegionName];
var view = region.Views.FirstOrDefault(x => x.GetType() == type);
if (view == null)
{
view = _container.Resolve(type, source);
region.Add(view);
}
region.Activate(view);
var para = parameters.GetValue<NavigationParameters>("navigationParameters");
_dependencyService.RegionManager.RequestNavigate(RegionName, source, para);
}
#endregion
}
}
注意事项
ViewModel可使用事件控制View界面元素
比如TreeView控件置顶,ViewModel定义委托事件,View中操作控件;
// ViewModel
public event EventHandler ScrollToTopEvent;
ScrollToTopEvent?.Invoke(this, EventArgs.Empty);
public XXView()
{
InitializeComponent();
if (this.DataContext is XXViewModel vm)
{
vm.ScrollToTopEvent += Vm_ScrollToTopEvent;
}
}
private void Vm_ScrollToTopEvent(object sender, System.EventArgs e)
{
WSCommFunc.TreeViewScrollToTop(TreeView1);
}
ViewModel内最好不要与用户交互
比如选择文件,可以在View中实现,在ViewModel中同步;
// View
<Button Content="选择" x:Name="ButtonSelectFile" Command="{Binding SelectFileCommand}" Click="ButtonSelectFile_Click" />
private void ButtonSelectFile_Click(object sender, System.Windows.RoutedEventArgs e)
{
// System.Windows.Forms.OpenFileDialog openfile 选择文件
var btn = (Button)sender;
btn.CommandParameter = new FileInfo(openfile.FileName);
}
// ViewModel
private void SelectFile_Click(object parameter)
{
if (parameter is FileInfo fi)
{
var fileName = fi.Name;
var filePath = fi.FullName;
}
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步