回答しないといいましたが、コメントだけでは伝えられそうにないので回答します^^;
文字数制限があるので可能な限りシンプルに、NumericUpDown
を題材にさせていただきました(超雑なのは目をつぶってください^^;
6パターンあります。
- ベタ置き
- 部分ビュー的
- カスタムコントロール的
- オリジナル
- 継承
- 添付プロパティ
イメージとしてはベタ置きで書いていたがゴチャついてきたので、部分ビュー的に切り出した。
その後複数個使いたくなったので、カスタムコントロール的に作り替えたといった感じです。
もちろんNumericUpDown
ならカスタムコントロールにするのがベストですが、使いまわす気がないなら手前で留めておくのもありです。
MVVMで実装する前提で回答を頂けるとありがたいです。
とのことですので後半3つは無理やり作りましたが、個人的には意味が分かんないですね。
部分ビュー的・カスタムコントロール的の面倒なところをわざわざ合わせたというか無駄にまどろっこしいというか、「それ何の意味があるの?」感が伝わりますかね?^^;
MainWindow
xml
1<Window
2 x:Class="Q2x9yv8s160mb6u.MainWindow"
3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
5 xmlns:local="clr-namespace:Q2x9yv8s160mb6u"
6 Width="800"
7 Height="450">
8 <Window.DataContext>
9 <local:MainViewModel />
10 </Window.DataContext>
11 <UniformGrid Columns="3">
12 <GroupBox Header="ベタ置き">
13 <StackPanel>
14 <TextBlock Text="{Binding Value}" />
15 <RepeatButton Command="{Binding IncrementCommand}" Content="Up" />
16 <RepeatButton Command="{Binding DecrementCommand}" Content="Down" />
17 <TextBlock Text="{Binding Value, StringFormat=今の値は {0} です}" />
18 </StackPanel>
19 </GroupBox>
20
21 <GroupBox Header="部分ビュー的">
22 <StackPanel>
23 <local:UserControl1 DataContext="{Binding UserControl1ViewModel}" />
24 <TextBlock Text="{Binding UserControl1ViewModel.Value, StringFormat=今の値は {0} です}" />
25 </StackPanel>
26 </GroupBox>
27
28 <GroupBox Header="カスタムコントロール的">
29 <StackPanel>
30 <local:UserControl2 x:Name="userControl2" />
31 <TextBlock Text="{Binding Value, ElementName=userControl2, StringFormat=今の値は {0} です}" />
32 <!-- もちろんこうなっていてもいい(以下3・4・5も同様) -->
33 <!--<local:UserControl2 Value="{Binding Hoge}" />
34 <TextBlock Text="{Binding Hoge, StringFormat=今の値は {0} です}" />-->
35 </StackPanel>
36 </GroupBox>
37
38 <GroupBox Header="オリジナル">
39 <StackPanel>
40 <local:UserControl3 x:Name="userControl3" />
41 <TextBlock Text="{Binding Value, ElementName=userControl3, StringFormat=今の値は {0} です}" />
42 </StackPanel>
43 </GroupBox>
44
45 <GroupBox Header="継承">
46 <StackPanel>
47 <local:UserControl4 x:Name="userControl4" />
48 <TextBlock Text="{Binding Value, ElementName=userControl4, StringFormat=今の値は {0} です}" />
49 </StackPanel>
50 </GroupBox>
51
52 <GroupBox Header="添付プロパティ">
53 <StackPanel>
54 <local:UserControl5 x:Name="userControl5" />
55 <TextBlock Text="{Binding (local:UserControl5.Value), ElementName=userControl5, StringFormat=今の値は {0} です}" />
56 </StackPanel>
57 </GroupBox>
58 </UniformGrid>
59</Window>
cs
1using System.Windows;
2using CommunityToolkit.Mvvm.ComponentModel;
3using CommunityToolkit.Mvvm.Input;
4
5namespace Q2x9yv8s160mb6u
6{
7 public class UserControlViewModel : ObservableObject
8 {
9 public int Value { get => _Value; set => SetProperty(ref _Value, value); }
10 private int _Value;
11
12 public RelayCommand IncrementCommand { get; }
13 public RelayCommand DecrementCommand { get; }
14
15 public UserControlViewModel()
16 {
17 IncrementCommand = new(() => Value++);
18 DecrementCommand = new(() => Value--);
19 }
20 }
21
22 public class MainViewModel : UserControlViewModel // 同じものを書くのが無駄なので継承で済ませた^^;
23 {
24 public UserControlViewModel UserControl1ViewModel { get; } = new();
25 }
26
27 public partial class MainWindow : Window
28 {
29 public MainWindow() => InitializeComponent();
30 }
31}
UserControl1(部分ビュー的)
xml
1<UserControl
2 x:Class="Q2x9yv8s160mb6u.UserControl1"
3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
5 <StackPanel>
6 <TextBlock Text="{Binding Value}" />
7 <RepeatButton Command="{Binding IncrementCommand}" Content="Up" />
8 <RepeatButton Command="{Binding DecrementCommand}" Content="Down" />
9 </StackPanel>
10</UserControl>
cs
1using System.Windows.Controls;
2
3namespace Q2x9yv8s160mb6u
4{
5 public partial class UserControl1 : UserControl
6 {
7 public UserControl1() => InitializeComponent();
8 }
9}
UserControl2(カスタムコントロール的)
xml
1<UserControl
2 x:Class="Q2x9yv8s160mb6u.UserControl2"
3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
5 xmlns:local="clr-namespace:Q2x9yv8s160mb6u">
6 <StackPanel>
7 <TextBlock Text="{Binding Value, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:UserControl2}}}" />
8 <RepeatButton Click="UpButton_Click" Content="Up" />
9 <RepeatButton Click="DownButton_Click" Content="Down" />
10 </StackPanel>
11</UserControl>
cs
1using System.Windows;
2using System.Windows.Controls;
3
4namespace Q2x9yv8s160mb6u
5{
6 public partial class UserControl2 : UserControl
7 {
8 public int Value { get => (int)GetValue(ValueProperty); set => SetValue(ValueProperty, value); }
9 public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(nameof(Value), typeof(int), typeof(UserControl2), new PropertyMetadata(0));
10
11 public UserControl2() => InitializeComponent();
12
13 private void UpButton_Click(object sender, RoutedEventArgs e) => Value++;
14 private void DownButton_Click(object sender, RoutedEventArgs e) => Value--;
15 }
16}
UserControl3(オリジナル)
xml
1<UserControl
2 x:Class="Q2x9yv8s160mb6u.UserControl3"
3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
5 <StackPanel>
6 <TextBlock Text="{Binding Value}" />
7 <RepeatButton Command="{Binding IncrementCommand}" Content="Up" />
8 <RepeatButton Command="{Binding DecrementCommand}" Content="Down" />
9 </StackPanel>
10</UserControl>
cs
1using System.Windows;
2using System.Windows.Controls;
3using System.Windows.Data;
4
5namespace Q2x9yv8s160mb6u
6{
7 public partial class UserControl3 : UserControl
8 {
9 public int Value { get => (int)GetValue(ValueProperty); set => SetValue(ValueProperty, value); }
10 public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(nameof(Value), typeof(int), typeof(UserControl3), new PropertyMetadata(0));
11
12 public UserControl3()
13 {
14 InitializeComponent();
15 var vm = new UserControlViewModel();
16 //vm.PropertyChanged += (s, e) => Value = vm.Value;
17 // コードでバインドする?
18 SetBinding(ValueProperty, new Binding(nameof(vm.Value)));
19 DataContext = vm;
20 }
21 }
22}
UserControl4(継承)
xml
1<local:UserControl4Base
2 x:Class="Q2x9yv8s160mb6u.UserControl4"
3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
5 xmlns:local="clr-namespace:Q2x9yv8s160mb6u"
6 Value="{Binding Value}">
7 <StackPanel>
8 <TextBlock Text="{Binding Value}" />
9 <RepeatButton Command="{Binding IncrementCommand}" Content="Up" />
10 <RepeatButton Command="{Binding DecrementCommand}" Content="Down" />
11 </StackPanel>
12</local:UserControl4Base>
cs
1using System.Windows;
2using System.Windows.Controls;
3
4namespace Q2x9yv8s160mb6u
5{
6 // <local:UserControl4Base x:Class="Q2x9yv8s160mb6u.UserControl4" Value="{Binding Value}">
7 // こう書けるようにするため、仕方なく間にクラスを挟む
8 public class UserControl4Base : UserControl
9 {
10 public int Value { get => (int)GetValue(ValueProperty); set => SetValue(ValueProperty, value); }
11 public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(nameof(Value), typeof(int), typeof(UserControl4Base), new PropertyMetadata(0));
12 }
13
14 public partial class UserControl4 : UserControl4Base
15 {
16 public UserControl4()
17 {
18 InitializeComponent();
19 DataContext = new UserControlViewModel();
20 }
21 }
22}
UserControl5(添付プロパティ)
xml
1<UserControl
2 x:Class="Q2x9yv8s160mb6u.UserControl5"
3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
5 xmlns:local="clr-namespace:Q2x9yv8s160mb6u"
6 local:UserControl5.Value="{Binding Value}">
7 <StackPanel>
8 <TextBlock Text="{Binding Value}" />
9 <RepeatButton Command="{Binding IncrementCommand}" Content="Up" />
10 <RepeatButton Command="{Binding DecrementCommand}" Content="Down" />
11 </StackPanel>
12</UserControl>
cs
1using System.Windows;
2using System.Windows.Controls;
3
4namespace Q2x9yv8s160mb6u
5{
6 public partial class UserControl5 : UserControl
7 {
8 public static readonly DependencyProperty ValueProperty = DependencyProperty.RegisterAttached("Value", typeof(int), typeof(UserControl5), new PropertyMetadata(0));
9 public static int GetValue(DependencyObject obj) => (int)obj.GetValue(ValueProperty);
10 public static void SetValue(DependencyObject obj, int value) => obj.SetValue(ValueProperty, value);
11
12 public UserControl5()
13 {
14 InitializeComponent();
15 DataContext = new UserControlViewModel();
16 }
17 }
18}
