0

私はWPFアプリケーションを作成していて、MVVMパターンを自分自身に教えようとしています。サミュエルジャックのサイトにある手順を使用しています:http: //blog.functionalfun.net/2008/09/hooking-up-commands-to-events-in-wpf.html

コマンドをボタンにバインドし、すべてを接続しました。コマンドクラスは、ICommandを実装するViewModelクラスの内部クラスです。複雑な部分は、ボタンから実行されるコマンドがビューのデータにアクセスする必要がある場合です。C#の内部クラスは外部クラスのメンバーにアクセスできないため、データを内部クラスに渡すためだけに、ViewModelcalssでパブリック静的変数を宣言する必要があります。これは、ハックでエレガントでない解決策のようです。誰かがこれを行うためのより良い方法を持っていますか?

私の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>

どうもありがとう!

4

2 に答える 2

1

コマンドクラスがデータを取得するために使用するデリゲートまたはイベントをビューモデルに含めることができます

..または、コマンドパラメータを介してビューからコマンドにデータを渡すことができます。

Button Command="{Binding SaveCommand}" 
        CommandParameter="{Binding SelectedItem, Element=listBox}" />
于 2013-02-14T20:18:37.930 に答える
1

RelayCommandデリゲートを呼び出すことができるクラスを定義できます。このアプローチでは、コマンドごとにクラスを宣言する必要はありません。

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
}

次のようにボタンのXAMLを更新することを忘れないでください。

<Button Grid.Row="0" Grid.Column="2" HorizontalAlignment="Right" Width="100" Height="20" Margin="3" Background="LightCyan" Content="Search" Command="{Binding SearchButtonPressed}" />

そして、他のボタンについても同じです。

お役に立てれば!

于 2013-02-14T20:33:26.143 に答える