[英]How to share data between ViewModel class and ICommand classes using MVVM in WPF application?
我正在编写一个WPF应用程序并尝试自学MVVM模式。 我正在使用Samuel Jack网站上的说明: http : //blog.functionalfun.net/2008/09/hooking-up-commands-to-events-in-wpf.html
我已将命令绑定到按钮上并将所有内容连接起来。 命令类是ViewModel类的内部类,它实现ICommand。 复杂的部分是从我的按钮运行的命令需要访问我的视图上的数据。 由于C#内部类不能访问外部类的成员,我发现自己必须在ViewModel calss中声明公共静态变量,才能将数据传递给内部类。 这似乎是一个hackish和不优雅的解决方案。 有没有人有更好的方法来做到这一点?
我的ViewModel代码:
public class ApplicationViewModel
{
public ObservableCollection<App> AppCollection { get; set; }
static string searchString;
static string emailString;
public App SelectedApp { get; set; }
public string AppToSearch
{
get
{
return searchString;
}
set
{
searchString = value;
}
}
public string AppToRequest
{
get
{
get emailString;
}
set
{
// set static email String here
}
}
private SearchButtonCommand searchButtonCmd;
private ClearButtonCommand clearButtonCmd;
private EmailButtonCommand emailButtonCmd;
public ApplicationViewModel()
{
this.AppCollection = ApplicationsModel.Current;
}
public ICommand SearchButtonPressed
{
get
{
if (this.searchButtonCmd == null)
{
this.searchButtonCmd = new SearchButtonCommand();
}
return this.searchButtonCmd;
}
}
public ICommand ClearButtonPressed
{
get
{
if (this.clearButtonCmd == null)
{
this.clearButtonCmd = new ClearButtonCommand();
}
return this.clearButtonCmd;
}
}
public ICommand EmailButtonPressed
{
get
{
if (this.emailButtonCmd == null)
{
this.emailButtonCmd = new EmailButtonCommand();
}
return this.emailButtonCmd;
}
}
private class SearchButtonCommand : ICommand
{
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
string searchkey = ApplicationViewModel.searchString;
ApplicationsModel.Current.Search(searchkey);
}
public bool CanExecute(object parameter)
{
return true;
}
}
private class ClearButtonCommand : ICommand
{
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
ApplicationsModel.Current.ClearSearch();
}
public bool CanExecute(object parameter)
{
return true;
}
}
private class EmailButtonCommand : ICommand
{
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
string targetEmail = ApplicationViewModel.emailString;
}
public bool CanExecute(object parameter)
{
return true;
}
}
}
我的XAML:
<Window.DataContext>
<vm:ApplicationViewModel />
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Grid.Row="0" Height="84" HorizontalAlignment="Left" Margin="0,5,5,5" Name="imgLogo" Stretch="Fill" VerticalAlignment="Top" Width="600" Source="C:\Images\bannerlong.png" />
<Grid Grid.Row="1" HorizontalAlignment="Center" Margin="0,5,5,5" VerticalAlignment="Center">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content="Search for Application">
<Label.Foreground>
<SolidColorBrush Color="LightCyan" />
</Label.Foreground>
</Label>
<TextBox Grid.Row="0" Grid.Column="1" Margin="3" Width="500" Text="{Binding AppToSearch}" />
<Button Grid.Row="0" Grid.Column="2" HorizontalAlignment="Right" Width="100" Height="20" Margin="3" Background="LightCyan" Content="Search" vm:ButtonBehaviour.SearchCommand="{Binding SearchButtonPressed}" />
<Button Grid.Row="0" Grid.Column="3" HorizontalAlignment="Right" Width="100" Height="20" Margin="3" Background="LightCyan" Content="Clear Search" vm:ButtonBehaviour.ClearCommand="{Binding ClearButtonPressed}"/>
</Grid>
<ListView Grid.Row="2" BorderBrush="Black" HorizontalAlignment="Stretch" ItemsSource="{Binding Path=AppCollection}" SelectedItem="{Binding SelectedApp}">
<ListView.View>
<GridView>
<GridViewColumn Header="Application Name" Width="100" DisplayMemberBinding="{Binding Name}"/>
<GridViewColumn Header="Application Description" Width="800" DisplayMemberBinding="{Binding Description}"/>
<GridViewColumn Header="Application Owner" Width="100" DisplayMemberBinding="{Binding Owner}"/>
</GridView>
</ListView.View>
</ListView>
<Button Grid.Row="3" HorizontalAlignment="Center" Width="200" Height="30" Margin="3" Background="LightCyan" Content="Request Application" vm:ButtonBehaviour.EmailCommand="{Binding EmailButtonPressed}" />
</Grid>
非常感谢!
您可以在viewmodel中使用命令类来获取数据的委托或事件
..或者您可以通过命令参数将视图中的数据传递给命令。
Button Command="{Binding SaveCommand}"
CommandParameter="{Binding SelectedItem, Element=listBox}" />
您可以定义一个允许您调用委托的RelayCommand
类。 使用此方法,您无需为每个Command声明一个类。
public class RelayCommand : ICommand
{
#region Miembros
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
#endregion
#region Constructor
public RelayCommand(Action<object> execute)
: this(execute, null)
{
}
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
{
throw new ArgumentNullException("execute");
}
_execute = execute;
_canExecute = canExecute;
}
#endregion
#region Miembros de ICommand
public bool CanExecute(object parameter)
{
return _canExecute == null || _canExecute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
_execute(parameter);
}
#endregion
}
然后你的ViewModel类将是这样的:
public class ApplicationViewModel
{
public ObservableCollection<App> AppCollection { get; set; }
private string searchString;
private string emailString;
public App SelectedApp { get; set; }
public string AppToSearch
{
get
{
return searchString;
}
set
{
searchString = value;
}
}
public string AppToRequest
{
get
{
return emailString;
}
set { emailString = value; }
}
private ICommand searchButtonCmd;
private ICommand clearButtonCmd;
private ICommand emailButtonCmd;
public ApplicationViewModel()
{
this.AppCollection = ApplicationsModel.Current;
}
public ICommand SearchButtonPressed
{
get
{
if (this.searchButtonCmd == null)
{
this.searchButtonCmd = new RelayCommand(SearchButtonPressedExecute, c=>CanSearch);
}
return this.searchButtonCmd;
}
}
private void SearchButtonPressedExecute(object parameter)
{
ApplicationsModel.Current.Search(searchString);
}
public bool CanSearch
{
get { return true; }
}
// TODO: You can figure out the rest of the code
}
不要忘记更新Button的XAML,如:
<Button Grid.Row="0" Grid.Column="2" HorizontalAlignment="Right" Width="100" Height="20" Margin="3" Background="LightCyan" Content="Search" Command="{Binding SearchButtonPressed}" />
和其他按钮一样。
希望这可以帮助!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.