web-dev-qa-db-ja.com

DataTemplateのボタンをフォームのViewModelのコマンドにバインドする

私の問題はこの質問で説明されているものと似ています:
DataTemplateのWPF MVVMボタンコントロールバインディング

ここに私のXAMLがあります:

<Window x:Class="MissileSharp.Launcher.MainWindow"
        xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml"
        Title="MissileSharp Launcher" Height="350" Width="525">
    <Grid>
        <!-- when I put the button here (outside the list), the binding works -->
        <!--<Button Content="test" Command="{Binding Path=FireCommand}" />-->
        <ListBox ItemsSource="{Binding CommandSets}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <!-- I need the button here (inside the list), and here the binding does NOT work -->
                    <Button Content="{Binding}" Command="{Binding Path=FireCommand}" />
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
</Window>

これはListBoxであり、CommandSetsという名前のObservableCollection<string>にバインドされています(これはViewModelにあります)。
このバインディングは機能します(コレクション内の各アイテムのボタンを表示します)。

次に、ボタンをコマンド(FireCommand)にバインドします。これもViewModelにあります。
ViewModelの関連部分は次のとおりです。

public class MainWindowViewModel : INotifyPropertyChanged
{
    public ICommand FireCommand { get; set; }
    public ObservableCollection<string> CommandSets { get; set; }

    public MainWindowViewModel()
    {
        this.FireCommand = new RelayCommand(new Action<object>(this.FireMissile));
    }

    private void FireMissile(Object obj)
    {
        System.Windows.MessageBox.Show("fire");
    }
}

このボタンのバインドは機能しません。
上記でリンクした question から理解したことから、バインディングが機能しません。
(間違っている場合は訂正してください)

  • ボタンはListBox内にあるため、ListBox(この場合はObservableCollection)のバインディングのみを「認識」しますが、メインウィンドウのバインディングは認識しません。
  • メインウィンドウのメインViewModel(ボタンが「認識しない」)のコマンドにバインドしようとしています

コマンド自体は間違いなく正しいです。なぜなら、ボタンを外側に配置すると、ListBox(上のXAMLの例を参照)、バインディングが機能し、コマンドが実行されます。

どうやら、フォームのメインViewModelにバインドするようにボタンに指示する必要があるだけです。
しかし、正しいXAML構文を理解できません。

グーグルで見つけたいくつかの方法を試しましたが、どれもうまくいきませんでした。

<Button Content="{Binding}" Command="{Binding RelativeSource={RelativeSource Window}, Path=DataContext.FireCommand}" />

<Button Content="{Binding}" Command="{Binding Path=FireCommand, Source={StaticResource MainWindow}}" />

<Button Content="{Binding}" Command="{Binding Path=FireCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" />

誰かが喜んでくれますか:

  1. ListBox内のボタンをフォームのMainViewModel?のコマンドにバインドするための適切なXAMLを教えてください
  2. wPF/MVVM初心者が理解できるように、この高度なバインディングに関する説明が記載されているリンクを私に教えてください。
    私はただ難解なXAMLの呪文をコピーして貼り付けているような気がします、そして今のところ、どのようにして私はどのような手掛かりも持っていません(そして良いドキュメントを見つけることができません) RelativeSourceStaticResourceなど、「通常の」バインディングの代わりに何が必要かを自分で判断します。
26

それは:

{Binding DataContext.FireCommand,
         RelativeSource={RelativeSource AncestorType=ListBox}}

途中でDataContextを実際に変更しない限り、ルートまで移動する必要はありませんが、ListBoxはメインのプロパティにバインドしているようですVM =これで十分です。

私が読むことをお勧めする唯一のものは データバインディングの概要Binding class ドキュメント(そのプロパティを含む)です。


バインディングがどのように構成されるかについての簡単な説明もここにあります:バインディングはsourcePathsourceを基準として、デフォルトではsourceは現在のDataContextです。明示的に設定できるソースは、SourceElementNameRelativeSourceです。これらのいずれかを設定すると、DataContextsourceとしてオーバーライドされます。

したがって、RelativeSourceのようなsourceを使用し、そのレベルのDataContext内の何かにアクセスする場合、DataContextPathに表示される必要があります。

61
H.B.

これはほとんどの人とは無関係であると考えられますが、この検索は、Xamarinフォームに関連するため、データテンプレート内のコントロールへのデータバインディングコマンドを検索した結果の3つのうちの1つにすぎません。だから、多分それは、今日の誰かを助けるでしょう。

私のように、BindableLayout内でコマンドをバインドする方法について疑問に思うかもしれません。 Xamarinフォーラムでこれに回答したjesulink2514の功績をたたえます。すべてのコメントのため、おそらくそれは多くの人から見落とされています。これが彼の解決策ですが、私は以下のリンクを含めています:

<ContenPage x:Name="MainPage">
<ListView Grid.Row="1"
              ItemsSource="{Binding Customers}"
              VerticalOptions="Fill"
              x:Name="ListviewCustomer">
      <ListView.ItemTemplate>
        <DataTemplate>
      <Label Text="{Binding Property}"/>
          <Button Command="{Binding BindingContext.ItemCommand, Source={x:Reference MainPage}}" 
                         CommandParameter="{Binding .}">Click me</Button>
        </DataTemplate>
      </ListView.ItemTemplate>
    </ListView>
</ContentPage>

https://forums.xamarin.com/discussion/comment/217355/#Comment_217355

0
smoovey