设置命令.Button1Command中的Parameter1,并使用该命令的值.Button2Command中的Par



我有两个按钮命令。让我们称它们为BrowseButton1LoadButton1。第一个命令浏览一个文件路径(MVVM对象(,并将其设置为我的机器的本地路径。然后,第二个ICommand(也称为LoadButton1(使用该文件路径(同一MVVM对象(将一些数据加载到SQL表中。

我的问题是,我不能在第二个ICommand中使用文件路径的值,因为它返回null

XAML代码

<Window x:Class="TestEnvironment.MainWIndowTestStackOverflow"
x:Name="MainWindowTestStackOverflow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:TestEnvironment"
mc:Ignorable="d"
Height="720"
Width="1145"
ResizeMode="NoResize"
WindowStartupLocation="CenterScreen"
BorderBrush="Black"
BorderThickness="1.5,1.5,1.5,1.5"
WindowStyle="None">
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</Window.Resources>
<Grid x:Name="GridMain"
Width="1145"
Background="White"
HorizontalAlignment="Center"
ShowGridLines="False" 
Grid.Row="1">
<!--Grid Columns-->
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0"/>
<ColumnDefinition Width="195"/>
<ColumnDefinition Width="295"/>
<ColumnDefinition Width="650"/>
<ColumnDefinition Width="0"/>
</Grid.ColumnDefinitions>
<!--Grid Rows-->
<Grid.RowDefinitions>
<RowDefinition Height="0"/>
<RowDefinition Height="45"/>
<RowDefinition Height="45"/>
<RowDefinition Height="45"/>
<RowDefinition Height="45"/>
<RowDefinition Height="52"/>
<RowDefinition Height="400"/>
</Grid.RowDefinitions>
<TextBox
Name="FileNameTextBox"
Text="{Binding Path=FilesFilePath}"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Margin="5,0,0,0"
IsReadOnly="True"
FontStyle="Italic"
FontFamily="Arial"
FontSize="9"
BorderThickness="0"
Grid.Column="2"
Grid.Row="1"/>
<!--Apply ICommand to browse file 1st time-->
<Button 
x:Name="BrowseButton1"
Content="Browse"
Command="{Binding Path=BrowseButtonCommand}"
IsEnabled="{Binding Path=EnableFilesBrowseButton, Converter={StaticResource BooleanToVisibilityConverter}}"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Width="80" 
Height="25"
Margin="40,0,0,0"
Padding="0"
FontWeight="Light"
FontSize="10"
Grid.Column="3"
Grid.Row="1"
Cursor="Hand">
<Button.CommandParameter>
<MultiBinding>
<MultiBinding.Converter>
<local:BrowseButtonConverter/>
</MultiBinding.Converter>
<Binding Path="FilesFilePath"/> //this is the value I want to exchange between the two ICommands
<Binding Path="EnableFilesBrowseButton"/>
<Binding Path="EnableFilesLoadButton"/>
<Binding Path="EnableFilesViewButton"/>
<Binding Path="FilesPanelVisibility"/>
</MultiBinding>
</Button.CommandParameter>
</Button>
<Button 
x:Name="LoadButton1"
Content="Load"
Command="{Binding Path=LoadButtonCommand}"
IsEnabled="{Binding Path=EnableFilesLoadButton, Converter={StaticResource BooleanToVisibilityConverter}}"
Focusable="False"
Width="80"
Height="25"
Margin="135,0,0,0"
FontSize="10"
FontWeight="Light"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Grid.Column="3"
Grid.Row="1"
Cursor="Hand">
<Button.CommandParameter>
<MultiBinding>
<MultiBinding.Converter>
<local:LoadButtonConverter/>
</MultiBinding.Converter>
<Binding Path="FilesFilePath"/> //this returns null even though browse button return the FilesFilePath
</MultiBinding>
</Button.CommandParameter>
</Button>
</Grid>
</Window>

.cs文件

namespace TestEnvironment
{
//Command parameters -Browse Button
public class BrowseButtonCommandParameters
{
public string FilePathSelected { get; set; } //parameter 1
public bool EnableBrowseButton { get; set; } //parameter 2
public bool EnableLoadButton { get; set; } //parameter 3
}
//Browse - MultiValueConverter
class BrowseButtonConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
// Error handling omitted for brevity
// Casting omitted because question's code has insufficient context
return new BrowseButtonCommandParameters
{
FilePathSelected = (string)values[0],
EnableBrowseButton = (bool)values[1],
EnableLoadButton = (bool)values[2],
};
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotSupportedException("to-source binding mode not supported");
}
private static BrowseButtonConverter _converter = null;
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (_converter == null) _converter = new BrowseButtonConverter();
return _converter;
}
public BrowseButtonConverter()
: base()
{
}
}
//Command parameters -Load Button
public class LoadButtonCommandParameters
{
public string FilePathSelected { get; set; } //parameter 1
}
//Load - MultiValueConverter
class LoadButtonConverter : MarkupExtension, IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
// Error handling omitted for brevity
// Casting omitted because question's code has insufficient context
return new LoadButtonCommandParameters
{
FilePathSelected = (string)values[0], //this is actually the FilePath defined from Browse Command.
};
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotSupportedException("to-source binding mode not supported");
}
private static LoadButtonConverter _converter = null;
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (_converter == null) _converter = new LoadButtonConverter();
return _converter;
}
public LoadButtonConverter()
: base()
{
}
}
//----------------------------------------------------------------------------------------------------
public class MainWindowViewModel : INotifyPropertyChanged
{
//MVVM objects bound to XAML objects and connected to ICommand parameters
//Used by BrowseButton1
//1.
private bool _enableFilesLoadButton;
public bool EnableFilesLoadButton
{
get
{
return _enableFilesLoadButton;
}
set
{
_enableFilesLoadButton = value;
OnPropertyChanged("EnableFilesLoadButton");
}
}
//2.
private bool _enableFilesBrowseButton;
public bool EnableFilesBrowseButton
{
get
{
return _enableFilesBrowseButton;
}
set
{
_enableFilesBrowseButton = value;
OnPropertyChanged("EnableFilesBrowseButton");
}
}
//3.
private string _FilesFilePath;
public string FilesFilePath
{
get
{
return _FilesFilePath;
}
set
{
_FilesFilePath = value;
OnPropertyChanged("FilesFilePath");
}
}
//----------------------------------------------------------------------------------------------------
//ICommand: BrowseButtonCommand
public ICommand BrowseButtonCommand
{
get { return new DelegateCommand<object>(FuncBrowseCommand); }
}
public void FuncBrowseCommand(object parameters)
{
var param = (BrowseButtonCommandParameters)parameters;
Nullable<bool> browse_result = BrowseFile(param.FilePathSelected); //command parameter 1, FilesFilePath
Debug.WriteLine("FilesFilePath " + FilesFilePath);
//Load button gets instantly disabled when every time the user clicks the Browse Button 
param.EnableLoadButton = false; //command parameter 2
Debug.WriteLine("EnableLoadButton: " + EnableFilesLoadButton);
//Browse file
if (browse_result == true)
{
param.EnableLoadButton = true; //command parameter 2
Debug.WriteLine("EnableLoadButton: " + EnableFilesLoadButton);
param.EnableBrowseButton = true; //command parameter 3
Debug.WriteLine("EnableBrowseButton: " + EnableFilesBrowseButton);
}
else
{
return;
}
}
public void FuncLoadButton(object parameters)
{
var param = (LoadButtonCommandParameters)parameters;
Debug.Writeline("FilePath: "+ param.FilePathSelected); //this returns null
}
//Browse function used in Browse ICommand
public bool BrowseFile(string filepathselected)
{
// Create OpenFileDialog
OpenFileDialog openFileDlg = new OpenFileDialog();
// Launch OpenFileDialog by calling ShowDialog method
Nullable<bool> result = openFileDlg.ShowDialog();
Debug.WriteLine("1. browse window result: " + result);
// Set filter for file extension and default file extension  
openFileDlg.DefaultExt = ".csv";
openFileDlg.Filter = "All files (*.*)|*.*|CSV file (*.csv)|*.csv|Text files (*.txt)|*.txt";
// Set initial directory
openFileDlg.InitialDirectory = @"C:Documents";
openFileDlg.Title = "Browse Files";
openFileDlg.CheckFileExists = true;
openFileDlg.CheckPathExists = true;
openFileDlg.RestoreDirectory = true;
// Multiple selection with all file types
openFileDlg.Multiselect = true;
// Get the selected file name and display in a TextBox.
// Load content of file in a TextBlock
if (result == true)
{
filepathselected = openFileDlg.FileName;
Debug.WriteLine("2. File Path: " + filepathselected);
}
return (bool)result;
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string property)
{
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
}
}
}

这两个代码片段将帮助您重现我的问题。问题是FilesFilePath命令参数都不能将其值传递给Load command,也不能在MainWindow UI中查看DataContext中的任何更改。即使"浏览"按钮为参数FilesFilePath赋予了值,UI也无法显示此文本。回想一下,FileNameTextBox的属性.TextFilesFilePath绑定。所以我希望UI也显示该文本。

总之,根据提供的代码片段,我有两个目标要实现

  • 在两个ICommand之间传递FilesFilePath(字符串(的值
  • 使用浏览ICommand后,在UI中查看FilesFilePath(字符串(的值

如果您不清楚,我非常愿意在评论中提供任何其他信息。

您的代码不起作用的原因是您从未设置FilesFilePath属性。

BrowseFile方法中,如果resulttrue:,则应设置FilesFilePath

//Browse function used in Browse ICommand
public bool BrowseFile(string filepathselected)
{
...
// Get the selected file name and display in a TextBox.
// Load content of file in a TextBlock
if (result == true)
{
filepathselected = openFileDlg.FileName;
// Set the FilesFilePath property here!
FilesFilePath = filepathselected;
Debug.WriteLine("2. File Path: " + filepathselected);
}
return (bool)result;
}

最新更新