繁体   English   中英

如何在WPF应用程序中使用MVVM在ViewModel类和ICommand类之间共享数据?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM