0

ダミーのWPFアプリケーション(MVVM指向)を入手したとしましょう。メインウィンドウには、作成したカスタムリストが含まれ、リストにはカスタムアイテムが含まれています。アイテムには画像ボタンがあり、ボタンコマンドをビューモデルで取得したコマンドにします。ビューモデルはメインウィンドウにバインドされています。どうすればいいですか?

ダミープロジェクトを添付しました(ここからダウンロード: http://www.2shared.com/file/qmO3E5rx/NestedCommand.html またはここ:http : //www.multiupload.nl/KCFLSKAIH0)、

ただし、ダウンロードしたくない場合、コードは次のようになります。

MainWindow XAML:

<Window x:Class="WpfApplication2.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:Application="clr-namespace:WpfApplication2"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <Application:List x:Name="myList" DataContext="{Binding}" />
</Grid>

MainWindowコードビハインド:

        public MainWindow()
    {
        InitializeComponent();
        CharacterViewModel viewModel = new CharacterViewModel();
        this.myList.ItemsList.ItemsSource = viewModel.Model.Powers;
    }

XAMLのリスト:

<UserControl x:Class="WpfApplication2.List"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:Application="clr-namespace:WpfApplication2"
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">
<Grid>
    <ListView x:Name="ItemsList" ItemsSource="{Binding Path=Name}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <Application:Item x:Name="myItem" />
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</Grid>

アイテムXAML:

<UserControl x:Class="WpfApplication2.Item"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" 
         d:DesignHeight="50" d:DesignWidth="50">
<Grid>
    <Button x:Name="ButtonImage" Command="**????????**">
        <Button.Template>
            <ControlTemplate>
                <Border HorizontalAlignment="Center" VerticalAlignment="Center" >
                    <Image Width="50" Height="50" Source="/WpfApplication2;component/Images/Jellyfish.jpg"/>
                </Border>
            </ControlTemplate>
        </Button.Template>
    </Button>
</Grid>

ViewModelコード:

    public class CharacterViewModel : ObjectBase
{
    public Character Model { get; private set; }
    public DelegateCommand<object> RemoveCommand { get; private set; }

    public CharacterViewModel()
        : this(Character.Create())
    {
    }

    public CharacterViewModel(Character model)
    {
        Model = model;
        RemoveCommand = new DelegateCommand<object>(RemoveCommand_Execute, RemoveCommand_CanExecute, "Save");
    }

    void RemoveCommand_Execute(object arg)
    {
        Model.Powers.Clear();
        MessageBox.Show(string.Format("{0} character powers removed.", Model.Name));
    }

    bool RemoveCommand_CanExecute(object arg)
    {
        return Model.Name != string.Empty;
    }
}

モデルコード:

public class Character : ObjectBase
{
    string _Name = string.Empty;
    ObservableCollection<string> _Powers = new ObservableCollection<string>();

    public string Name
    {
        get { return _Name; }
        set
        {
            if (_Name == value)
                return;

            _Name = value;
            OnPropertyChanged("Name");
        }
    }

    public ObservableCollection<string> Powers
    {
        get { return _Powers; }
    }

    public static Character Create()
    {
        Character hero = new Character()
        {
            Name = "Superman",
        };

        hero.Powers.Add("Flight");
        hero.Powers.Add("Strength");
        hero.Powers.Add("X-Ray Vision");

        return hero;
    }
}

フレームワークコード:

public class DelegateCommand<T> : ICommand
{
    public DelegateCommand(Action<T> execute) : this(execute, null) { }

    public DelegateCommand(Action<T> execute, Predicate<T> canExecute) : this(execute, canExecute, "") { }

    public DelegateCommand(Action<T> execute, Predicate<T> canExecute, string label)
    {
        _Execute = execute;
        _CanExecute = canExecute;

        Label = label;
    }

    readonly Action<T> _Execute = null;
    readonly Predicate<T> _CanExecute = null;

    public string Label { get; set; }

    public void Execute(object parameter)
    {
        _Execute((T)parameter);
    }

    public bool CanExecute(object parameter)
    {
        return _CanExecute == null ? true : _CanExecute((T)parameter);
    }

    public event EventHandler CanExecuteChanged
    {
        add
        {
            if (_CanExecute != null)
                CommandManager.RequerySuggested += value;
        }
        remove
        {
            if (_CanExecute != null)
                CommandManager.RequerySuggested -= value;
        }
    }
}

public abstract class ObjectBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected internal void OnPropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

助けてくれてありがとう

4

1 に答える 1

1

ListItem の DataContext は、それがバインドされているアイテムであり、探しているものではありません。UserControl の DataContext を探しています。それを取得するには、ElementNameを使用して明示的に UserControl を参照するか、 RelativeSourceバインディングを使用してビジュアル ツリーを探索する必要があります。RelativeSource はおそらく最良のソリューションであり、コントロール自体を参照するため、DataContext で RemoveCommand メンバーを探しているバインディングのパスで指定する必要がありますPath=DataContext.RemoveCommand。以下の完全な例を参照してください。

XAML:

<Grid DataContext="{Binding}"> <!-- Set the binding for the DataContext of the control and all of its children -->
    <ListView ItemsSource="{Binding Path=Model.Powers}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <!-- Use RelativeSource to access the Grid control and then get its DataContext -->
                <Button Command="{Binding Path=DataContext.RemoveCommand, RelativeSource={RelativeSource AncestorType=Grid}}">
                    <Border HorizontalAlignment="Center" VerticalAlignment="Center" >
                        <Image Width="50" Height="50" Source="/WpfApplication2;component/Images/Jellyfish.jpg"/>
                    </Border>
                </Button>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</Grid>
于 2012-04-29T04:44:11.797 に答える