Prism 8.0
xmlns:prism="http://prismlibrary.com/"
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.SyncDataRecordRegion}"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch"/>
View事件 ViewModel响应
UserControl
using Microsoft.Xaml.Behaviors.Wpf;
xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
<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 { get; private set; }
LoadedCommand = new DelegateCommand(UserControl_Loaded);
public DelegateCommand LoadedCommand => new DelegateCommand(UserControl_Loaded);
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">
<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}"/>
</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);
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>
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 + Dialog
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);
}
注意事项
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;
}
}