質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

UWP

UWPは、Universal Windows Platformの略。様々なデバイス向けに提供されているアプリケーションを共通のフレームワーク上で動作可能にする仕組みで、Windows10で導入されました。

XAML

XAML(Extensible Application Markup Language)はWPF、Silverlight、Windows PhoneそしてWindows Store appsでユーザーインターフェースを定義するために使われるXML言語です。

バインド

バインドは、一定の方法で複数の事柄が関連付けられている状態を呼びます。また、そのような関連付けを実行する機能自体を指す事もあります。

button

HTMLで用いる<button>タグです。

Q&A

解決済

1回答

2504閲覧

独自のViewModelを持つUserControl内のButtonのCommandを親のPage(UserControlを使う側)からCommandをバインドする方法

hirotamasami

総合スコア5

Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

UWP

UWPは、Universal Windows Platformの略。様々なデバイス向けに提供されているアプリケーションを共通のフレームワーク上で動作可能にする仕組みで、Windows10で導入されました。

XAML

XAML(Extensible Application Markup Language)はWPF、Silverlight、Windows PhoneそしてWindows Store appsでユーザーインターフェースを定義するために使われるXML言語です。

バインド

バインドは、一定の方法で複数の事柄が関連付けられている状態を呼びます。また、そのような関連付けを実行する機能自体を指す事もあります。

button

HTMLで用いる<button>タグです。

1グッド

0クリップ

投稿2020/10/28 02:31

前提・実現したいこと

UWPで独自のViewModelを持つUserControl内のButtonのCommandを親のPage(UserControlを使う側)からCommandをバインドさせたいです。
[試したこと]で記載のように作成したのですが、
クリックしても、Commandに入れたメソッドは実行されませんでした。

この場合はどのように作成すればよろしいでしょうか?
※Prismなどは使用しません。

このようなサイトでの質問もまだ慣れておらず、情報不足ありましたら
ご指摘ください。
宜しくお願い致します。

試したこと

まずUserControl側は

C#

1using System.Windows.Input; 2using Windows.UI.Xaml; 3using Windows.UI.Xaml.Controls; 4 5namespace ParentBindTest.Views 6{ 7 public sealed partial class ChildControl : UserControl 8 { 9 public readonly DependencyProperty OnClickCommandProperty = 10 DependencyProperty.Register( 11 nameof(OnClickCommand), 12 typeof(ICommand), 13 typeof(ChildControl), 14 new PropertyMetadata(default(ICommand))); 15 16 public ICommand OnClickCommand 17 { 18 get { return (ICommand)GetValue(OnClickCommandProperty); } 19 set 20 { 21 SetValue(OnClickCommandProperty, value); 22 } 23 } 24 25 public ChildControl() 26 { 27 this.InitializeComponent(); 28 } 29 } 30} 31 32<UserControl 33 x:Class="ParentBindTest.Views.ChildControl" 34 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 35 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 36 xmlns:local="using:ParentBindTest.Views" 37 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 38 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 39 mc:Ignorable="d" 40 x:Name="Child_Control"> 41 42 <UserControl.DataContext> 43 <local:ChildControlViewModel/> 44 </UserControl.DataContext> 45 46 <Grid> 47 <Grid.RowDefinitions> 48 <RowDefinition Height="1*"/> 49 <RowDefinition Height="1*"/> 50 </Grid.RowDefinitions> 51 52 <Grid.ColumnDefinitions> 53 <ColumnDefinition Width="1*"/> 54 <ColumnDefinition Width="1*"/> 55 </Grid.ColumnDefinitions> 56 57<!-- 58 <local:GrandchildButton Grid.Row="0" Grid.Column="0" Margin="2" Command="{Binding Child_Control.OnClickCommand}"/> 59 <local:GrandchildButton Grid.Row="0" Grid.Column="1" Margin="2" Command="{Binding Child_Control.OnClickCommand, Mode=TwoWay}"/> 60 <local:GrandchildButton Grid.Row="0" Grid.Column="1" Command="{Binding OnClickCommand ,RelativeSource={RelativeSource Self}}"/> 61--> 62 <local:GrandchildButton Grid.Row="0" Grid.Column="0" Background="Blue" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Command="{Binding OnClickCommand ,ElementName=Child_Control}"/> 63 <local:GrandchildButton Grid.Row="0" Grid.Column="1" Background="Red" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Command="{Binding OnClickCommand ,ElementName=Child_Control}"/> 64 <local:GrandchildButton Grid.Row="1" Grid.Column="0" Background="Yellow" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Command="{Binding OnClickCommand ,ElementName=Child_Control}"/> 65 <local:GrandchildButton Grid.Row="1" Grid.Column="1" Background="Green" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Command="{Binding OnClickCommand ,ElementName=Child_Control}"/> 66 67 </Grid> 68 69</UserControl>

以上のようなコントロールを作成しました
GrandchildButtonはButton型の独自のコントロールです。

C#

1<Button 2 x:Class="ParentBindTest.Views.GrandchildButton" 3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5 xmlns:local="using:ParentBindTest.Views" 6 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 7 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 8 mc:Ignorable="d"> 9 10 <Button.DataContext> 11 <local:GrandchildButtonViewModel/> 12 </Button.DataContext> 13 14</Button> 15

このUserControlをPageで使用し、
以下のようにそのPageのViewModelでCommandを作成し、
Bindさせました。

C#

1<Page 2 x:Class="ParentBindTest.Views.ParentPage" 3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5 xmlns:local="using:ParentBindTest.Views" 6 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 7 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 8 mc:Ignorable="d"> 9 10 <Page.DataContext> 11 <local:ParentPageViewModel/> 12 </Page.DataContext> 13 14 <local:ChildControl Margin="5" 15 OnClickCommand="{Binding ClickCommand , Mode=TwoWay}"/> 16 17</Page> 18 19using System; 20using System.Windows.Input; 21 22namespace ParentBindTest.Views 23{ 24 /// <summary>ParentPageViewModel クラスは、ParentPageのViewModelクラスです。</summary> 25 public class ParentPageViewModel 26 { 27 public ICommand ClickCommand { get; private set; } 28 29 public ParentPageViewModel() 30 { 31 ClickCommand = new RelayCommand(OnButtonClick); 32 } 33 34 private void OnButtonClick() 35 { 36 //クリック時の処理 37 } 38 } 39 40 public class RelayCommand : ICommand 41 { 42 private readonly Action _execute; 43 private readonly Func<bool> _canExecute; 44 45 public event EventHandler CanExecuteChanged; 46 47 public RelayCommand(Action execute) 48 { 49 if (execute == null) 50 throw new ArgumentNullException("execute"); 51 _execute = execute; 52 } 53 54 public bool CanExecute(object parameter) 55 { 56 return _canExecute == null ? true : _canExecute(); 57 } 58 59 public void Execute(object parameter) 60 { 61 _execute(); 62 } 63 64 public void RaiseCanExecuteChanged() 65 { 66 CanExecuteChanged?.Invoke(this, EventArgs.Empty); 67 } 68 } 69} 70

以上のように作成しましたが、
ClickCommandに入れたOnButtonClickは
実行されませんでした。

補足情報(FW/ツールのバージョンなど)

・OS バージョン Windows10

TN8001👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

あれこれやっていたらこれで動きました。
ElementNameだとうまくいかないようです(なんでかはわかりません)

xml

1<Page 2 x:Class="Questions300833.MainPage" 3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5 xmlns:local="using:Questions300833" 6 x:Name="Main_Page" 7 Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> 8 <Page.DataContext> 9 <local:ParentPageViewModel /> 10 </Page.DataContext> 11 <Grid> 12 <local:ChildControl Margin="5" OnClickCommand="{x:Bind ((local:ParentPageViewModel)Main_Page.DataContext).ClickCommand}" /> 13 </Grid> 14</Page>

xml

1<UserControl 2 x:Class="Questions300833.ChildControl" 3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5 xmlns:local="using:Questions300833" 6 x:Name="Child_Control"> 7 <UserControl.DataContext> 8 <local:ChildControlViewModel /> 9 </UserControl.DataContext> 10 <Grid> 11 <Grid.RowDefinitions> 12 <RowDefinition /> 13 <RowDefinition /> 14 </Grid.RowDefinitions> 15 <Grid.ColumnDefinitions> 16 <ColumnDefinition /> 17 <ColumnDefinition /> 18 </Grid.ColumnDefinitions> 19 <local:GrandchildButton 20 HorizontalAlignment="Stretch" 21 VerticalAlignment="Stretch" 22 Background="Blue" 23 Command="{x:Bind ((local:ChildControl)Child_Control).OnClickCommand}" /> 24 25 <!-- 省略 --> 26 </Grid> 27</UserControl>

独自のViewModelを持つUserControl

くどいですが、ここからずれているように思います。
これをしなければCommand="{Binding ClickCommand}"とするだけだったのに、わざわざややこしいことをしているように感じます。

DataTemplateでViewModelからUserControlを起こすのならわかるのですが、それぞれ何の関連もなくParentPageVMChildControlVMGrandchildButtonVMを作って嬉しい状況が思いつきません。

投稿2020/11/05 09:20

編集2023/08/12 15:26
TN8001

総合スコア9862

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hirotamasami

2020/11/06 02:17 編集

ご回答ありがとうございます。 上記方法で実装するとうまく動作しました。 xaml上でキャストなんてできるんですね・・・ 感動してしまいました。 すいません。 まだUWPに限らずいろいろ初心者なので View系はViewModel(とModel)が絶対つけるのがルールかと思ってたのもそうなのですが、 ユーザーコントロールにまとめた要素に対して ユーザーコントロールを使う側に依存しない部分は 可能な限りユーザーコントロール内に追いやって、 それ以外の部分を今回のように ユーザーコントロールを使う側から実装したいと考え このような形になりました。 次に似たような構成になるときは、 ViewModelを使わない形も視野に入れ実装いたします。 今回の質問の目的はDataContextがふさがってる場合の Commandの渡し方だったのでとても勉強になりました。 ありがとうございました。 また何かございましたらよろしくお願いします。
TN8001

2020/11/06 03:06

>ユーザーコントロールを使う側に依存しない部分は >可能な限りユーザーコントロール内に追いやって、 これは正しいです。 <UserControl.DataContext> <local:ChildControlViewModel/> </UserControl.DataContext> これがトラブルの元です。 やるのだったら <Grid.DataContext> <local:ChildControlViewModel/> </Grid.DataContext> このように内部の何かにつけることはあります。 コードビハインドに書いたほうが、シンプルに済む場合もあるでしょう。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問