🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

MVVM

MVVM(Model View ViewModel)は構築上のデザインパターンで、表現ロジック(ViewModel)によってデータ(Model)からページ(View)を分離させます。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

Q&A

解決済

2回答

3490閲覧

ObservableCollectionの任意のコレクションのメソッドから他のコレクションの値を変更することはできますか?

MomenToufu

総合スコア10

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

MVVM

MVVM(Model View ViewModel)は構築上のデザインパターンで、表現ロジック(ViewModel)によってデータ(Model)からページ(View)を分離させます。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

1グッド

0クリップ

投稿2021/03/26 01:41

環境

環境:VS2019
言語:C# WPF
ターゲットフレームワーク:.NET5
他にPrism をNugetでインストールしています。

前提・実現したいこと

ボタンコントロールのクリックで、ある要素のVisility の値を変更しようとしています。
この時、ボタンコントロールの各パラメータはObservableCollectionに入れ、Bindして表示しています。

次の図が、それにになります。
イメージ説明
(図1)

任意のボタンが押されたとき、そのボタンをバインドしているコレクションの値と、その他のコレクションの値を変更したいと思っています(図2)。ただ現在は、クリックしたボタンにバインドしているコレクションのメソッドを呼び出す方法しかわからないため、他のコレクションの値を変更することができていません。

イメージ説明
(図2)

そこで、タイトルの質問になりますが、あるコレクションのメソッドから他のコレクションの値を変更する事ってできないですよね?

該当のソースコード

ViewModel

C#

1using System; 2using System.Collections.Generic; 3using System.Linq; 4using System.Text; 5using System.Threading.Tasks; 6 7using Prism.Mvvm; 8using Prism.Commands; 9using System.Diagnostics;//Debug.WriteLine 10using System.ComponentModel;//PropertyChangedEventArgs 11using System.Collections.ObjectModel;//ObservableCollection 12 13namespace WpfApp1 14{ 15 class MainViewModel : BindableBase 16 { 17 /// <summary> 18 /// Menuリスト(View⇔ViewModel) 19 /// </summary> 20 public ObservableCollection<MenuModel> MenuModels{ get; private set; } 21 22 23 MainViewModel() 24 { 25 ObservableCollection<MenuModel> Tmp = new(); 26 Tmp.Add(new MenuModel() 27 { 28 SideMenuBackground = "#fff", 29 SideMenuForeground = "#000", 30 HomeMenuVisibility = "Collapsed", 31 SideMenuVisibility = "Visible", 32 Visibility = "Visible",//Hidden / Collapsed / Visible 33 Icon = "\xE10F", 34 Content = "HOME", 35 Note = "" 36 }); 37 Tmp.Add(new MenuModel() 38 { 39 SideMenuBackground = "{x:Null}", 40 SideMenuForeground = "#fff", 41 HomeMenuVisibility = "Visible", 42 SideMenuVisibility = "Visible", 43 Visibility = "Hidden",//Hidden / Collapsed / Visible 44 Icon = "\xF157", 45 Content = "CONTENT1", 46 Note = "Content1 です。ここには、content1 の説明が入ります。" 47 }); 48 Tmp.Add(new MenuModel() 49 { 50 SideMenuBackground = "{x:Null}", 51 SideMenuForeground = "#fff", 52 HomeMenuVisibility = "Visible", 53 SideMenuVisibility = "Visible", 54 Visibility = "Hidden",//Hidden / Collapsed / Visible 55 Icon = "\xF158", 56 Content = "CONTENT2", 57 Note = "Content2 です。ここには、content2 の説明が入ります。" 58 }); 59 Tmp.Add(new MenuModel() 60 { 61 SideMenuBackground = "{x:Null}", 62 SideMenuForeground = "#fff", 63 HomeMenuVisibility = "Visible", 64 SideMenuVisibility = "Visible", 65 Visibility = "Hidden",//Hidden / Collapsed / Visible 66 Icon = "\xF159", 67 Content = "CONTENT3", 68 Note = "Content3 です。ここには、content3 の説明が入ります。" 69 }); 70 this.MenuModels = Tmp; 71 } 72 73 public DelegateCommand<MenuModel> ClickMenu { get; } = new DelegateCommand<MenuModel>(x => 74 { 75 x.ChangeParameter(); 76 }); 77 } 78} 79

Model

C#

1using System; 2using System.Collections.Generic; 3using System.Linq; 4using System.Text; 5using System.Threading.Tasks; 6 7using Prism.Mvvm; 8using Prism.Commands; 9using System.Diagnostics;//Debug.WriteLine 10using System.ComponentModel;//PropertyChangedEventArgs 11using System.Collections.ObjectModel;//ObservableCollection 12 13namespace WpfApp1 14{ 15 class MenuModel : BindableBase 16 { 17 /// <summary> 18 /// Side Menu の文字色 19 /// </summary> 20 private string _SideMenuForeground; 21 public string SideMenuForeground 22 { 23 get { return _SideMenuForeground; } 24 set { SetProperty(ref this._SideMenuForeground, value); } 25 } 26 /// <summary> 27 /// Side Menu の背景 28 /// </summary> 29 private string _SideMenuBackground; 30 public string SideMenuBackground 31 { 32 get { return _SideMenuBackground; } 33 set { SetProperty(ref this._SideMenuBackground, value); } 34 } 35 36 /// <summary> 37 /// Home Menu への表示・非表示 38 /// </summary> 39 private string _HomeMenuVisibility; 40 public string HomeMenuVisibility 41 { 42 get { return _HomeMenuVisibility; } 43 set { SetProperty(ref this._HomeMenuVisibility, value); } 44 } 45 /// <summary> 46 /// Side Menu への表示・非表示 47 /// </summary> 48 private string _SideMenuVisibility; 49 public string SideMenuVisibility 50 { 51 get { return _SideMenuVisibility; } 52 set { SetProperty(ref this._SideMenuVisibility, value); } 53 } 54 /// <summary> 55 /// Mainの表示・非表示 56 /// </summary> 57 private string _Visibility; 58 public string Visibility 59 { 60 get { return _Visibility; } 61 set { SetProperty(ref this._Visibility, value); } 62 } 63 /// <summary> 64 /// アイコン 65 /// </summary> 66 private string _Icon; 67 public string Icon 68 { 69 get { return this._Icon; } 70 set { SetProperty(ref this._Icon, value); } 71 } 72 73 /// <summary> 74 /// コンテンツ名 75 /// </summary> 76 private string _Content; 77 public string Content 78 { 79 get { return this._Content; } 80 set { SetProperty(ref this._Content, value); } 81 } 82 /// <summary> 83 /// 説明 84 /// </summary> 85 private string _Note; 86 public string Note 87 { 88 get { return this._Note; } 89 set { SetProperty(ref this._Note, value); } 90 } 91 92 public void ChangeParameter() 93 { 94 Debug.WriteLine($"ChangeParameter : {this.Content}"); 95 this.Visibility = "Visible"; 96 this.SideMenuBackground = "#fff"; 97 this.SideMenuForeground = "#000"; 98 } 99 } 100} 101 102

View

XAML

1<Window x:Class="WpfApp1.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 5 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 6 xmlns:local="clr-namespace:WpfApp1" 7 mc:Ignorable="d" 8 Title="MainWindow" Height="14.2cm" Width="23cm" MinHeight="14.2cm" MinWidth="13cm"> 9 10 <Window.DataContext> 11 <local:MainViewModel/> 12 </Window.DataContext> 13 14 <Grid> 15 <Grid.ColumnDefinitions> 16 <ColumnDefinition Width="2cm"/> 17 <ColumnDefinition MinWidth="21"/> 18 </Grid.ColumnDefinitions> 19 20 21 <!--HOME--> 22 <Grid Grid.Column="1" Visibility="{Binding MenuModels[0].Visibility}"> 23 <ScrollViewer> 24 <StackPanel> 25 <TextBlock 26 Margin="15,15,0,0" 27 FontSize="23pt" 28 Text="{Binding MenuModels[0].Content}" 29 Foreground="#808080" /> 30 31 <ItemsControl x:Name="MyItems" ItemsSource="{Binding MenuModels}"> 32 <ItemsControl.ItemTemplate> 33 <DataTemplate> 34 <Grid Margin="15,15,0,0" Visibility="{Binding HomeMenuVisibility}"> 35 <Border Background="#efebe9" CornerRadius="10" ></Border> 36 <Button 37 Command="{Binding ElementName=MyItems, Path=DataContext.ClickMenu}" 38 CommandParameter="{Binding}" 39 Background="{x:Null}" 40 BorderThickness="0" 41 Width="350" 42 Height="160"> 43 <StackPanel Margin="10" Width="330" Height="140"> 44 <StackPanel Orientation="Horizontal"> 45 <TextBlock Text="{Binding Icon}" 46 FontFamily="Segoe MDL2 Assets" 47 FontSize="18pt" 48 Margin="10,0,10,0" 49 HorizontalAlignment="Center" 50 VerticalAlignment="Center"/> 51 <TextBlock Text="{Binding Content}" 52 FontSize="18pt"/> 53 </StackPanel> 54 <TextBlock 55 FontSize="11pt" 56 TextWrapping="Wrap" 57 Text="{Binding Note}"/> 58 </StackPanel> 59 </Button> 60 </Grid> 61 </DataTemplate> 62 </ItemsControl.ItemTemplate> 63 <ItemsControl.ItemsPanel> 64 <ItemsPanelTemplate> 65 <WrapPanel HorizontalAlignment="Center" Margin="0,0,0,0"/> 66 </ItemsPanelTemplate> 67 </ItemsControl.ItemsPanel> 68 </ItemsControl> 69 </StackPanel> 70 71 </ScrollViewer> 72 </Grid> 73 74 <!--CONTENT1--> 75 <Grid Grid.Column="1" Visibility="{Binding MenuModels[1].Visibility}"> 76 <ScrollViewer> 77 <StackPanel> 78 <TextBlock 79 Margin="15,15,0,0" 80 FontSize="23pt" 81 Text="{Binding MenuModels[1].Content}" 82 Foreground="#808080" /> 83 </StackPanel> 84 </ScrollViewer> 85 </Grid> 86 87 88 <!--CONTENT2--> 89 <Grid Grid.Column="1" Visibility="{Binding MenuModels[2].Visibility}"> 90 <ScrollViewer> 91 <StackPanel> 92 <TextBlock 93 Margin="15,15,0,0" 94 FontSize="23pt" 95 Text="{Binding MenuModels[2].Content}" 96 Foreground="#808080" /> 97 </StackPanel> 98 </ScrollViewer> 99 </Grid> 100 101 102 <!--CONTENT3--> 103 <Grid Grid.Column="1" Visibility="{Binding MenuModels[3].Visibility}"> 104 <ScrollViewer> 105 <StackPanel> 106 <TextBlock 107 Margin="15,15,0,0" 108 FontSize="23pt" 109 Text="{Binding MenuModels[3].Content}" 110 Foreground="#808080" /> 111 </StackPanel> 112 </ScrollViewer> 113 </Grid> 114 115 116 <!--サイドバー--> 117 <Grid Grid.Column="0" Background="#808080" > 118 119 <ItemsControl x:Name="MyItemsMenu" ItemsSource="{Binding MenuModels}"> 120 <ItemsControl.ItemTemplate> 121 <DataTemplate> 122 <Button 123 Command="{Binding ElementName=MyItemsMenu, Path=DataContext.ClickMenu}" 124 CommandParameter="{Binding}" 125 BorderThickness="0" 126 Background="{Binding SideMenuBackground}" 127 Margin="0,0,0,0" 128 Padding="10" 129 Foreground="{Binding SideMenuForeground}" > 130 <StackPanel> 131 <TextBlock 132 TextAlignment="Center" 133 FontSize="26pt" 134 Text="{Binding Icon}" 135 FontFamily="Segoe MDL2 Assets"/> 136 <TextBlock 137 TextAlignment="Center" 138 FontSize="8pt" 139 Text="{Binding Content}"/> 140 </StackPanel> 141 </Button> 142 </DataTemplate> 143 </ItemsControl.ItemTemplate> 144 <ItemsControl.ItemsPanel> 145 <ItemsPanelTemplate> 146 <StackPanel/> 147 </ItemsPanelTemplate> 148 </ItemsControl.ItemsPanel> 149 </ItemsControl> 150 </Grid> 151 </Grid> 152</Window> 153 154
TN8001👍を押しています

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

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

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

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

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

MomenToufu

2021/03/26 02:36

コメントありがとうございます。参考にしてみます。
guest

回答2

0

気になった点の改善版

文字数制限のためテンプレートは派手に削ったので、使用側でのカスタマイズ性はないです。キーボードナビゲーション回りもオミットしています^^;
それでもxamlは元より長くなってしまいましたorz

本体部分(Gridのところ)は非常に短くなりました。
MenuModelもスッキリしたと思いますがどうでしょうか?

MenuModelsObservableCollectionなので増減があると想定しましたが、固定数ならCollectionViewを使うまでもないです。

見た目を出来合いので済ませるならxamlの大部分は不要です。
例えばこういうの↓
Material Design In XAML Toolkit v3.2 の紹介 - Qiita

xml

1<Window 2 x:Class="Questions329889_2.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:Questions329889_2" 6 Width="23cm" 7 Height="14.2cm"> 8 9 <Window.DataContext> 10 <local:MainViewModel /> 11 </Window.DataContext> 12 13 <Window.Resources> 14 <Style x:Key="TabControlSidebarStyle" TargetType="{x:Type TabControl}"> 15 <Setter Property="Template"> 16 <Setter.Value> 17 <ControlTemplate TargetType="{x:Type TabControl}"> 18 <DockPanel> 19 <TabPanel Background="Gray" IsItemsHost="True" /> 20 <Border> 21 <ContentPresenter x:Name="PART_SelectedContentHost" ContentSource="SelectedContent" /> 22 </Border> 23 </DockPanel> 24 </ControlTemplate> 25 </Setter.Value> 26 </Setter> 27 </Style> 28 29 <Style x:Key="TabItemSidebarButtonStyle" TargetType="{x:Type TabItem}"> 30 <Setter Property="IsSelected" Value="{Binding IsSelected}" /> 31 <Setter Property="Foreground" Value="White" /> 32 <Setter Property="Background" Value="Gray" /> 33 <Setter Property="Template"> 34 <Setter.Value> 35 <ControlTemplate TargetType="{x:Type TabItem}"> 36 <Grid> 37 <Border x:Name="mainBorder" Background="{TemplateBinding Background}"> 38 <Border x:Name="innerBorder" Opacity="0" /> 39 </Border> 40 <ContentPresenter ContentSource="Header" Focusable="False" /> 41 </Grid> 42 <ControlTemplate.Triggers> 43 <DataTrigger Binding="{Binding IsMouseOver, RelativeSource={RelativeSource Self}}" Value="True"> 44 <Setter TargetName="mainBorder" Property="Background" Value="#FFBEE6FD" /> 45 </DataTrigger> 46 <DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource Self}}" Value="True"> 47 <Setter Property="Foreground" Value="Black" /> 48 <Setter Property="Background" Value="White" /> 49 <Setter TargetName="innerBorder" Property="Opacity" Value="1" /> 50 </DataTrigger> 51 </ControlTemplate.Triggers> 52 </ControlTemplate> 53 </Setter.Value> 54 </Setter> 55 </Style> 56 57 <DataTemplate x:Key="SidebarButtonTemplate" DataType="{x:Type local:MenuModel}"> 58 <Border Padding="6,10"> 59 <StackPanel> 60 <TextBlock 61 FontFamily="Segoe MDL2 Assets" 62 FontSize="26pt" 63 Text="{Binding Icon}" 64 TextAlignment="Center" /> 65 <TextBlock 66 FontSize="8pt" 67 Text="{Binding Title}" 68 TextAlignment="Center" /> 69 </StackPanel> 70 </Border> 71 </DataTemplate> 72 73 <DataTemplate x:Key="HomeContentTemplate" DataType="{x:Type local:MenuModel}"> 74 <ItemsControl ItemsSource="{Binding}"> 75 <ItemsControl.ItemTemplate> 76 <DataTemplate> 77 <Button 78 Width="350" 79 Height="160" 80 Margin="5" 81 Background="#efebe9" 82 Command="{Binding DataContext.ClickMenu, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" 83 CommandParameter="{Binding}"> 84 <Button.Template> 85 <ControlTemplate TargetType="{x:Type Button}"> 86 <Border 87 Name="border" 88 Background="{TemplateBinding Background}" 89 CornerRadius="10"> 90 <ContentPresenter /> 91 </Border> 92 <ControlTemplate.Triggers> 93 <Trigger Property="IsMouseOver" Value="True"> 94 <Setter TargetName="border" Property="Background" Value="#FFBEE6FD" /> 95 </Trigger> 96 </ControlTemplate.Triggers> 97 </ControlTemplate> 98 </Button.Template> 99 <DockPanel Margin="10"> 100 <StackPanel DockPanel.Dock="Top" Orientation="Horizontal"> 101 <TextBlock 102 Margin="10,0,10,0" 103 HorizontalAlignment="Center" 104 VerticalAlignment="Center" 105 FontFamily="Segoe MDL2 Assets" 106 FontSize="18pt" 107 Text="{Binding Icon}" /> 108 <TextBlock FontSize="18pt" Text="{Binding Title}" /> 109 </StackPanel> 110 <TextBlock 111 FontSize="11pt" 112 Text="{Binding Description}" 113 TextWrapping="Wrap" /> 114 </DockPanel> 115 </Button> 116 </DataTemplate> 117 </ItemsControl.ItemTemplate> 118 <ItemsControl.ItemsPanel> 119 <ItemsPanelTemplate> 120 <WrapPanel HorizontalAlignment="Center" /> 121 </ItemsPanelTemplate> 122 </ItemsControl.ItemsPanel> 123 </ItemsControl> 124 </DataTemplate> 125 126 <local:HomeContentTemplateSelector x:Key="HomeContentTemplateSelector" Template="{StaticResource HomeContentTemplate}" /> 127 128 <DataTemplate x:Key="MenuModelContentTemplate" DataType="{x:Type local:MenuModel}"> 129 <ScrollViewer> 130 <StackPanel> 131 <TextBlock 132 Margin="15" 133 FontSize="23pt" 134 Foreground="Gray" 135 Text="{Binding Title}" /> 136 <ContentPresenter 137 Margin="15" 138 Content="{Binding Content}" 139 ContentTemplateSelector="{StaticResource HomeContentTemplateSelector}" /> 140 </StackPanel> 141 </ScrollViewer> 142 </DataTemplate> 143 </Window.Resources> 144 145 <Grid> 146 <TabControl 147 ContentTemplate="{StaticResource MenuModelContentTemplate}" 148 ItemContainerStyle="{StaticResource TabItemSidebarButtonStyle}" 149 ItemTemplate="{StaticResource SidebarButtonTemplate}" 150 ItemsSource="{Binding MenuModels}" 151 Style="{StaticResource TabControlSidebarStyle}" 152 TabStripPlacement="Left" /> 153 154 <Button 155 Margin="15" 156 HorizontalAlignment="Right" 157 VerticalAlignment="Top" 158 Command="{Binding AddCommand}" 159 Content="Add" /> 160 </Grid> 161</Window>

cs

1using Prism.Commands; 2using Prism.Mvvm; 3using System.Collections.ObjectModel; 4using System.Windows; 5using System.Windows.Controls; 6using System.Windows.Data; 7 8namespace Questions329889_2 9{ 10 public class HomeContentTemplateSelector : DataTemplateSelector 11 { 12 public override DataTemplate SelectTemplate(object item, DependencyObject container) 13 => item is CollectionView ? Template : null; 14 public DataTemplate Template { get; set; } 15 } 16 17 public class MenuModel : BindableBase 18 { 19 public string Icon { get; init; } 20 public string Title { get; init; } 21 public string Description { get; init; } 22 public object Content { get; set; } 23 24 public bool IsSelected { get => _IsSelected; set => SetProperty(ref _IsSelected, value); } 25 private bool _IsSelected; 26 } 27 28 public class MainViewModel : BindableBase 29 { 30 public ObservableCollection<MenuModel> MenuModels { get; } 31 public DelegateCommand<MenuModel> ClickMenu { get; } 32 public DelegateCommand AddCommand { get; } 33 34 public MainViewModel() 35 { 36 MenuModels = new() 37 { 38 new() 39 { 40 IsSelected = true, 41 Icon = "\xE10F", 42 Title = "HOME", 43 }, 44 new() 45 { 46 Icon = "\xF157", 47 Title = "CONTENT1", 48 Description = "CONTENT1 です。ここには、CONTENT1 の説明が入ります。", 49 Content = "CONTENT1 です。", 50 }, 51 new() 52 { 53 Icon = "\xF158", 54 Title = "CONTENT2", 55 Description = "CONTENT2 です。ここには、CONTENT2 の説明が入ります。", 56 }, 57 new() 58 { 59 Icon = "\xF159", 60 Title = "CONTENT3", 61 Description = "CONTENT3 です。ここには、CONTENT3 の説明が入ります。", 62 }, 63 }; 64 65 MenuModels[0].Content = new ListCollectionView(MenuModels) 66 { 67 Filter = (x) => ((MenuModel)x).Title != "HOME", 68 }; 69 70 ClickMenu = new(x => 71 { 72 foreach (var m in MenuModels) 73 m.IsSelected = x == m; 74 }); 75 76 AddCommand = new(() => 77 { 78 MenuModels.Add(new() 79 { 80 Icon = "\xF159", 81 Title = $"CONTENT{number}", 82 Description = $"CONTENT{number} です。ここには、CONTENT{number} の説明が入ります。", 83 }); 84 number++; 85 }); 86 } 87 private int number = 4; 88 } 89 90 public partial class MainWindow : Window 91 { 92 public MainWindow() => InitializeComponent(); 93 } 94}

アプリ画像

投稿2021/03/29 03:03

編集2023/07/26 15:32
TN8001

総合スコア9855

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

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

MomenToufu

2021/03/29 04:35

こんな短時間ですごい! しかも追加する機能まで。 `MenuModel` もこんな簡単になって、いかに不要なものが多かったのがわかりました。 あとMVVMの切り分けの勉強にもなりました。 `ObservableCollection`を使ったのは、もともとは`MenuModel`の値の変更通知を取得したかったからです(今回提示いただいた内容だと、`IsSelected` の値)。 ただ、後からわかったのですが、`ObservableCollection`は増減する時に変更が通知されるようで orz
TN8001

2021/03/29 05:38

> こんな短時間ですごい! 事前に用意していただけです^^; > `ObservableCollection`を使ったのは、もともとは`MenuModel`の値の変更通知を取得したかったからです MenuModelsが増減しないなら、 - using System.Collections.ObjectModel; - using System.Windows.Data; + using System.Linq; - => item is CollectionView ? Template : null; + => item is IEnumerable<MenuModel> ? Template : null; - public ObservableCollection<MenuModel> MenuModels { get; } + public List<MenuModel> MenuModels { get; } - MenuModels[0].Content = new ListCollectionView(MenuModels) - { - Filter = (x) => ((MenuModel)x).Title != "HOME", - }; + MenuModels[0].Content = MenuModels.Skip(1); で十分です。当然`AddCommand`もAddボタンも動きませんので不要です。 コレクションの中身の変更通知がほしい場合は、一個一個登録することになります。 ReactivePropertyには、便利メソッドが用意されているようです。 [MVVM をリアクティブプログラミングで快適に ReactiveProperty オーバービュー 2020 年版 後編 - Qiita](https://qiita.com/okazuki/items/6faac7cb1a7d8a6ad0f2#observeelementproperty
MomenToufu

2021/03/30 00:43

ご丁寧にいろいろとありがとうございます。 参考にさせていただきます。 まだまだ、ちょくちょくわからないところありますが、調べながら理解したいと思います。
guest

0

ベストアンサー

あるコレクションのメソッドから他のコレクションの値を変更する事ってできないですよね?

ChangeParameterのところの話だと思いますが、表示・非表示を引数に全員回せばいいでしょう。

cs

1ClickMenu = new(x => 2{ 3 foreach (var m in MenuModels) 4 m.ChangeParameter(x == m); 5});

とりあえず提示コードを動かすなら、こんな感じでしょうか?

xml

1<Window 2 x:Class="Questions329889.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 3 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:Questions329889" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 4 Title="MainWindow" Width="23cm" Height="14.2cm" 5 MinWidth="13cm" MinHeight="14.2cm" mc:Ignorable="d"> 6 <Window.DataContext> 7 <local:MainViewModel /> 8 </Window.DataContext> 9 <Window.Resources> 10 <local:String2BrushConverter x:Key="String2BrushConverter" /> 11 </Window.Resources> 12 <Grid> 13 <Grid.ColumnDefinitions> 14 <ColumnDefinition Width="2cm" /> 15 <ColumnDefinition MinWidth="21" /> 16 </Grid.ColumnDefinitions> 17 18 <Grid Grid.Column="1" Visibility="{Binding MenuModels[0].Visibility}"> 19 <ScrollViewer> 20 <StackPanel> 21 <TextBlock 22 Margin="15,15,0,0" FontSize="23pt" Foreground="#808080" 23 Text="{Binding MenuModels[0].Content}" /> 24 25 <ItemsControl x:Name="MyItems" ItemsSource="{Binding MenuModels}"> 26 <ItemsControl.ItemTemplate> 27 <DataTemplate> 28 <Grid Margin="15,15,0,0" Visibility="{Binding HomeMenuVisibility}"> 29 <Border Background="#efebe9" CornerRadius="10" /> 30 <Button 31 Width="350" Height="160" Background="{x:Null}" 32 BorderThickness="0" Command="{Binding ElementName=MyItems, Path=DataContext.ClickMenu}" CommandParameter="{Binding}"> 33 <StackPanel 34 Width="330" Height="140" Margin="10"> 35 <StackPanel Orientation="Horizontal"> 36 <TextBlock 37 Margin="10,0,10,0" HorizontalAlignment="Center" VerticalAlignment="Center" 38 FontFamily="Segoe MDL2 Assets" FontSize="18pt" Text="{Binding Icon}" /> 39 <TextBlock FontSize="18pt" Text="{Binding Content}" /> 40 </StackPanel> 41 <TextBlock 42 FontSize="11pt" Text="{Binding Note}" TextWrapping="Wrap" /> 43 </StackPanel> 44 </Button> 45 </Grid> 46 </DataTemplate> 47 </ItemsControl.ItemTemplate> 48 <ItemsControl.ItemsPanel> 49 <ItemsPanelTemplate> 50 <WrapPanel HorizontalAlignment="Center" /> 51 </ItemsPanelTemplate> 52 </ItemsControl.ItemsPanel> 53 </ItemsControl> 54 </StackPanel> 55 </ScrollViewer> 56 </Grid> 57 58 <Grid Grid.Column="1" Visibility="{Binding MenuModels[1].Visibility}"> 59 <ScrollViewer> 60 <StackPanel> 61 <TextBlock 62 Margin="15,15,0,0" FontSize="23pt" Foreground="#808080" 63 Text="{Binding MenuModels[1].Content}" /> 64 </StackPanel> 65 </ScrollViewer> 66 </Grid> 67 68 <Grid Grid.Column="1" Visibility="{Binding MenuModels[2].Visibility}"> 69 <ScrollViewer> 70 <StackPanel> 71 <TextBlock 72 Margin="15,15,0,0" FontSize="23pt" Foreground="#808080" 73 Text="{Binding MenuModels[2].Content}" /> 74 </StackPanel> 75 </ScrollViewer> 76 </Grid> 77 78 <Grid Grid.Column="1" Visibility="{Binding MenuModels[3].Visibility}"> 79 <ScrollViewer> 80 <StackPanel> 81 <TextBlock 82 Margin="15,15,0,0" FontSize="23pt" Foreground="#808080" 83 Text="{Binding MenuModels[3].Content}" /> 84 </StackPanel> 85 </ScrollViewer> 86 </Grid> 87 88 <Grid Background="#808080"> 89 <ItemsControl x:Name="MyItemsMenu" ItemsSource="{Binding MenuModels}"> 90 <ItemsControl.ItemTemplate> 91 <DataTemplate> 92 <Button 93 Padding="10" Background="{Binding SideMenuBackground, Converter={StaticResource String2BrushConverter}}" BorderThickness="0" 94 Command="{Binding DataContext.ClickMenu, ElementName=MyItemsMenu}" CommandParameter="{Binding}" Foreground="{Binding SideMenuForeground, Converter={StaticResource String2BrushConverter}}"> 95 <StackPanel> 96 <TextBlock 97 FontFamily="Segoe MDL2 Assets" FontSize="26pt" Text="{Binding Icon}" 98 TextAlignment="Center" /> 99 <TextBlock 100 FontSize="8pt" Text="{Binding Content}" TextAlignment="Center" /> 101 </StackPanel> 102 </Button> 103 </DataTemplate> 104 </ItemsControl.ItemTemplate> 105 <ItemsControl.ItemsPanel> 106 <ItemsPanelTemplate> 107 <StackPanel /> 108 </ItemsPanelTemplate> 109 </ItemsControl.ItemsPanel> 110 </ItemsControl> 111 </Grid> 112 </Grid> 113</Window>

cs

1using Prism.Commands; 2using Prism.Mvvm; 3using System; 4using System.Collections.ObjectModel; 5using System.Diagnostics; 6using System.Globalization; 7using System.Windows; 8using System.Windows.Data; 9using System.Windows.Media; 10 11namespace Questions329889 12{ 13 public class String2BrushConverter : IValueConverter 14 { 15 public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 16 { 17 if (value is string s) 18 return new SolidColorBrush((Color)ColorConverter.ConvertFromString(s)); 19 return null; 20 } 21 public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => throw new NotImplementedException(); 22 } 23 24 public class MenuModel : BindableBase 25 { 26 public string SideMenuForeground { get => _SideMenuForeground; set => SetProperty(ref _SideMenuForeground, value); } 27 private string _SideMenuForeground; 28 29 public string SideMenuBackground { get => _SideMenuBackground; set => SetProperty(ref _SideMenuBackground, value); } 30 private string _SideMenuBackground; 31 32 public Visibility HomeMenuVisibility { get => _HomeMenuVisibility; set => SetProperty(ref _HomeMenuVisibility, value); } 33 private Visibility _HomeMenuVisibility; 34 35 public Visibility SideMenuVisibility { get => _SideMenuVisibility; set => SetProperty(ref _SideMenuVisibility, value); } 36 private Visibility _SideMenuVisibility; 37 38 public Visibility Visibility { get => _Visibility; set => SetProperty(ref _Visibility, value); } 39 private Visibility _Visibility; 40 41 public string Icon { get => _Icon; set => SetProperty(ref _Icon, value); } 42 private string _Icon; 43 44 public string Content { get => _Content; set => SetProperty(ref _Content, value); } 45 private string _Content; 46 47 public string Note { get => _Note; set => SetProperty(ref _Note, value); } 48 private string _Note; 49 50 public void ChangeParameter(bool visible) 51 { 52 if (visible) Debug.WriteLine($"Visible: {Content}"); 53 Visibility = visible ? Visibility.Visible : Visibility.Hidden; 54 SideMenuBackground = visible ? "#fff" : null; 55 SideMenuForeground = visible ? "#000" : "#fff"; 56 } 57 } 58 59 public class MainViewModel : BindableBase 60 { 61 public ObservableCollection<MenuModel> MenuModels { get; } 62 public DelegateCommand<MenuModel> ClickMenu { get; } 63 64 public MainViewModel() 65 { 66 MenuModels = new() 67 { 68 new() 69 { 70 SideMenuBackground = "#fff", 71 SideMenuForeground = "#000", 72 HomeMenuVisibility = Visibility.Collapsed, 73 SideMenuVisibility = Visibility.Visible, 74 Visibility = Visibility.Visible, 75 Icon = "\xE10F", 76 Content = "HOME", 77 }, 78 new() 79 { 80 SideMenuForeground = "#fff", 81 HomeMenuVisibility = Visibility.Visible, 82 SideMenuVisibility = Visibility.Visible, 83 Visibility = Visibility.Hidden, 84 Icon = "\xF157", 85 Content = "CONTENT1", 86 Note = "Content1 です。ここには、content1 の説明が入ります。", 87 }, 88 new() 89 { 90 SideMenuForeground = "#fff", 91 HomeMenuVisibility = Visibility.Visible, 92 SideMenuVisibility = Visibility.Visible, 93 Visibility = Visibility.Hidden, 94 Icon = "\xF158", 95 Content = "CONTENT2", 96 Note = "Content2 です。ここには、content2 の説明が入ります。", 97 }, 98 new() 99 { 100 SideMenuForeground = "#fff", 101 HomeMenuVisibility = Visibility.Visible, 102 SideMenuVisibility = Visibility.Visible, 103 Visibility = Visibility.Hidden, 104 Icon = "\xF159", 105 Content = "CONTENT3", 106 Note = "Content3 です。ここには、content3 の説明が入ります。", 107 }, 108 }; 109 110 ClickMenu = new(x => 111 { 112 foreach (var m in MenuModels) 113 m.ChangeParameter(x == m); 114 }); 115 } 116 } 117 118 public partial class MainWindow : Window 119 { 120 public MainWindow() => InitializeComponent(); 121 } 122}

気になった点

  • ボタンの扱いがおかしい(文字等がある部分までマウスを入れないと反応しない)
    見た目を変えるにはテンプレートを当ててください。
  • Viewだけの関心がViewModelMenuModel)に染み出している
    MenuModelでは選択されているという情報だけでいいと思います。
  • おそらくTabControlですっきり書けそう
    見た目を同じにするとなると、スタイル等で行数は変わらないかも?

投稿2021/03/26 10:00

編集2023/07/26 15:21
TN8001

総合スコア9855

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

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

MomenToufu

2021/03/29 01:22

TN8001さん、ありがとうございます。 想定していた動作となりました。 最初はTabコントロールをカスタマイズしようと考えていましたが、 MVVMを勉強していた時に、(極端なことを言えば)「TextBoxとObservableCollectionさえあれば何でも出来るんじゃ?」と思ったのが始まりで今回のような方法をとりました。 また理解できていない部分などありますが、回答いただいた内容をもとに勉強させていただきます。 ありがとうございました。
TN8001

2021/03/29 03:03

よくありそうで有用だと思うので、TabControl版も一応回答しておきました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問