下記 A の書き方の方が wpf として妥当ですしょうか?
その場合、妥当な理由は何かメリットがあるからでしょうか?
それとも、wpf のお約束とか設計思想的なものでしょうか?
よろしくお願いします。
(B に比べてプロパティが増えるのと、xamlが若干長くなるのを面倒に感じてます)
-- A --
- xaml
<ComboBox ItemsSource="{Binding AaaItemsSource, RelativeSource={RelativeSource AncestorType=Window}}">
</ComboBox>
- cs
public Dictionary<int, string> AaaItemsSource
{
get { return Ccc.Ddd; }
}
-- B --
- xaml
<ComboBox Name="cb1"></ComboBox>
- cs
public コンストラクタ()
{
cb1.ItemsSource = Ccc.Ddd;
}
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答1件
0
ベストアンサー
AはRelativeSource
を付けることはしません。
コンストラクタでDataContext = this;
として、ItemsSource="{Binding AaaItemsSource}"
と書きます。
通常はDataContext = new ViewModel();
と、ViewModel
クラスを作ります。
Bはそもそもバインドしていません。初期値として値を入れただけです(それで用が足りる場合は問題ありません)
しかしcb1.ItemsSource = Ccc.Ddd;
とするとMVVMから外れることになるので、バインドしてしまうかxamlで固定値を入れることが多いと思います。
xml
1<ComboBox> 2 <sys:String>A</sys:String> 3 <sys:String>B</sys:String> 4 <sys:String>C</sys:String> 5</ComboBox>
Dictionary
だと本質が見えにくいので、string
の場合の例です(全く面白くありませんが^^;
「確認」ボタンを押すと今の値を表示します。「倍!!」ボタンを押すと値が2倍に伸びます。
AはView
からViewModel
への変更のみ反映します(OneWayToSource
)
Bはバインドしていないので何も起きません。
Cは双方向に値が反映されます(TwoWay
)
方法: バインディングの方向を指定する - WPF | Microsoft Docs
ABCどれを選択するかは、要件から自動的に決まります。
xml
1<Window 2 x:Class="Questions285969.MainWindow" 3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5 xmlns:sys="clr-namespace:System;assembly=mscorlib" 6 Width="800" 7 Height="450"> 8 9 <StackPanel> 10 <!--<ComboBox> 11 <sys:String>A</sys:String> 12 <sys:String>B</sys:String> 13 <sys:String>C</sys:String> 14 </ComboBox>--> 15 16 <!-- A --> 17 <TextBox Text="{Binding A}" /> 18 19 <!-- B --> 20 <TextBox x:Name="textBox" /> 21 <!-- 意味的にはただこうしただけ --> 22 <!--<TextBox Text="B" />--> 23 24 <!-- C --> 25 <TextBox Text="{Binding C}" /> 26 27 <Button Click="Button_Click" Content="確認" /> 28 <Button Click="Button_Click_1" Content="倍!!" /> 29 </StackPanel> 30</Window>
cs
1using System.ComponentModel; 2using System.Runtime.CompilerServices; 3using System.Windows; 4 5namespace Questions285969 6{ 7 public partial class MainWindow : Window, INotifyPropertyChanged 8 { 9 public string A { get; set; } = "A"; 10 11 private string B = "B"; 12 13 public string C { get => c; set => Set(ref c, value); } 14 private string c = "C"; 15 16 public MainWindow() 17 { 18 InitializeComponent(); 19 DataContext = this; 20 textBox.Text = B; 21 } 22 23 private void Button_Click(object sender, RoutedEventArgs e) 24 { 25 MessageBox.Show($"A:{A}\nB:{B}\nC:{C}"); 26 27 // もちろんこうすれば表示されますが、そういうことはやめましょうというのが「MVVMパターン」です 28 // (このイベントハンドラ自体MVVMから外れてしまっていますが、そこは本題ではないので^^; 29 //MessageBox.Show($"A:{A}\nB:{textBox.Text}\nC:{C}"); 30 } 31 32 private void Button_Click_1(object sender, RoutedEventArgs e) 33 { 34 A += A; 35 B += B; 36 C += C; 37 38 // もちろんこうすれば変わりますが、以下略 39 //textBox.Text += textBox.Text; 40 } 41 42 43 #region INotifyPropertyChanged 44 public event PropertyChangedEventHandler PropertyChanged; 45 protected void Set<T>(ref T storage, T value, [CallerMemberName] string propertyName = null) 46 { 47 if(Equals(storage, value)) return; 48 storage = value; 49 OnPropertyChanged(propertyName); 50 } 51 protected void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 52 #endregion 53 } 54}
投稿2020/08/19 21:42
編集2023/07/23 04:34総合スコア9862
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/08/20 11:03