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

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

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

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

.NET Core

.NET Coreは、マネージソフトウェアフレームワークでオープンソースで実装されています。クロスプラットフォームを前提に考えられており、Windows/Mac/Linuxで動くアプリケーションを作成することが可能です。

.NET

.NETとは、主に.NET Frameworkと呼ばれるアプリケーションまたは開発環境を指します。CLR(共通言語ランタイム)を搭載し、入力された言語をCIL(共通中間言語)に変換・実行することが可能です。そのため、C#やPythonなど複数の言語を用いることができます。

C#

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

WPF

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

Q&A

解決済

1回答

3894閲覧

[WPF] DataTriggerのValueにはバインドできない?

dekaribon

総合スコア14

Windows 10

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

.NET Core

.NET Coreは、マネージソフトウェアフレームワークでオープンソースで実装されています。クロスプラットフォームを前提に考えられており、Windows/Mac/Linuxで動くアプリケーションを作成することが可能です。

.NET

.NETとは、主に.NET Frameworkと呼ばれるアプリケーションまたは開発環境を指します。CLR(共通言語ランタイム)を搭載し、入力された言語をCIL(共通中間言語)に変換・実行することが可能です。そのため、C#やPythonなど複数の言語を用いることができます。

C#

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

WPF

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

1グッド

0クリップ

投稿2021/06/24 15:01

実現したいこと

WPFのListBoxを使って、あるSNSのアカウントごとにAPIを使用してダイレクトメッセージをLINE風に表示しようとしています。
相手の発言が左、自分の発言が右に来るようにListBoxのStyleを動的に変更しようとしました。
アカウントを選択すると、そのアカウントの情報はVMのAccountに格納されます。
AccountData.Usernameが自分のユーザー名、DirectMessageItem.Usernameが相手のユーザー名になります。
この2つの変数をDataTriggerで比較して同一だった場合はHorizontalAlignmentプロパティをRightにすればいいかなと思ったんですが、DataTriggerのValueはバインドできませんでした。(Bindingは使えないというエラーメッセージ)
なのでDynamicResourcesを使おうと思ったんですが、調べてもResoucesに単純なstringをバインドする方法が見つかりませんでした。
なにか解決策はあるでしょうか?

コード

※省略してあります

ViewModel

C#

1public class DirectMessageViewModel 2{ 3 public ReactiveProperty<AccountData> Account { get; set; } = new(); 4 public ReactiveCollection<DirectMessageItem> MessageInfos { get; set; } = new(); 5}

View

XAML

1<ListBox Grid.Row="0" MinHeight="200" ItemsSource="{Binding MessageInfos}" 2 ScrollViewer.VerticalScrollBarVisibility="Auto" md:ThemeAssist.Theme="Dark" md:ListBoxAssist.IsToggle="False"> 3 <ListBox.ItemTemplate> 4 <DataTemplate> 5 <md:Card Margin="2" Padding="20" md:ShadowAssist.ShadowDepth="Depth2"> 6 <StackPanel> 7 <TextBlock Text="{Binding Username}" HorizontalAlignment="Center" /> 8 <Separator Margin="2 5" /> 9 <TextBlock Margin="10 0 0 0" Text="{Binding Message}" /> 10 </StackPanel> 11 </md:Card> 12 </DataTemplate> 13 </ListBox.ItemTemplate> 14</ListBox>

環境

.NET Framework v4.8

TN8001👍を押しています

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

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

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

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

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

guest

回答1

0

ベストアンサー

相手の発言が左、自分の発言が右に来るようにListBoxのStyleを動的に変更しようとしました。

正確にはListBoxItemContainerStyleで、ListBoxItemStyleDataTriggerで変えるということですね?

DataTriggerのValueはバインドできませんでした。(Bindingは使えないというエラーメッセージ)

できなかったことも「試したこと」として提示いただけると、やりたいことがはっきりして回答しやすいです。

DynamicResourcesを使おうと思ったんですが、調べてもResoucesに単純なstringをバインドする方法が見つかりませんでした。

こういうことか自信がありませんが、回答コードにはコメントで入れた通り結論はダメでした。

※省略してあります

もちろん全部出されても困りますが、もう少しないとこちらで再現コードを書く手間と認識があっているかの確信が持てないです^^;


前置きが長すぎましたが質問について、「wpf datatrigger value binding」で検索したところ↓がヒットしました。
.net - Using binding for the Value property of DataTrigger condition - Stack Overflow

コンバータが必要なのがちょっと気になります^^;(ほかのアプローチも何かありそうですが

xml

1<Window 2 x:Class="Questions345940.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:Questions345940" 6 xmlns:md="http://materialdesigninxaml.net/winfx/xaml/themes" 7 xmlns:sys="clr-namespace:System;assembly=mscorlib" 8 Width="400" 9 Height="600"> 10 <Window.Resources> 11 <local:MultiValueEqualityConverter x:Key="multiValueEqualityConverter" /> 12 <!--<sys:String x:Key="myname">dekaribon</sys:String>--> 13 </Window.Resources> 14 <Window.DataContext> 15 <local:DirectMessageViewModel /> 16 </Window.DataContext> 17 <DockPanel> 18 <DockPanel DockPanel.Dock="Bottom"> 19 <Button 20 Command="{Binding SendCommand}" 21 Content="send" 22 DockPanel.Dock="Right" /> 23 <RadioButton 24 Content="dekaribon" 25 IsChecked="{Binding IsChecked.Value}" 26 Style="{StaticResource MaterialDesignChoiceChipRadioButton}" /> 27 <RadioButton Content="TN8001" Style="{StaticResource MaterialDesignChoiceChipRadioButton}" /> 28 <TextBox VerticalAlignment="Center" md:HintAssist.Hint="message" /> 29 </DockPanel> 30 31 <ListBox md:ThemeAssist.Theme="Dark" ItemsSource="{Binding MessageInfos}"> 32 <ListBox.ItemContainerStyle> 33 <Style BasedOn="{StaticResource MaterialDesignListBoxItem}" TargetType="ListBoxItem"> 34 <Setter Property="HorizontalAlignment" Value="Left" /> 35 <Style.Triggers> 36 <DataTrigger Value="True"> 37 <DataTrigger.Binding> 38 <MultiBinding Converter="{StaticResource multiValueEqualityConverter}"> 39 <Binding Path="Username" /> 40 <Binding Path="DataContext.Account.Value.Username" RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type ListBox}}" /> 41 </MultiBinding> 42 </DataTrigger.Binding> 43 <Setter Property="HorizontalAlignment" Value="Right" /> 44 </DataTrigger> 45 46 <!-- XDG0062 'DynamicResourceExtension' は、有効なトリガーの条件ではありません。 --> 47 <!--<DataTrigger Binding="{Binding Username}" Value="{DynamicResource myname}"> 48 <Setter Property="HorizontalAlignment" Value="Right" /> 49 </DataTrigger>--> 50 </Style.Triggers> 51 </Style> 52 </ListBox.ItemContainerStyle> 53 <ListBox.ItemTemplate> 54 <DataTemplate> 55 <md:Card 56 Margin="2" 57 Padding="20" 58 md:ShadowAssist.ShadowDepth="Depth2"> 59 <StackPanel> 60 <TextBlock HorizontalAlignment="Center" Text="{Binding Username}" /> 61 <Separator Margin="2,5" /> 62 <TextBlock Margin="10,0,0,0" Text="{Binding Message}" /> 63 </StackPanel> 64 </md:Card> 65 </DataTemplate> 66 </ListBox.ItemTemplate> 67 </ListBox> 68 </DockPanel> 69</Window>

cs

1using Reactive.Bindings; 2using System; 3using System.Globalization; 4using System.Linq; 5using System.Windows; 6using System.Windows.Data; 7 8namespace Questions345940 9{ 10 // [.net - Using binding for the Value property of DataTrigger condition - Stack Overflow](https://stackoverflow.com/questions/2240421/using-binding-for-the-value-property-of-datatrigger-condition) 11 public class MultiValueEqualityConverter : IMultiValueConverter 12 { 13 public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 14 => values?.All(o => o?.Equals(values[0]) == true) == true || values?.All(o => o == null) == true; 15 public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) 16 => throw new NotImplementedException(); 17 } 18 19 public class AccountData 20 { 21 public string Username { get; set; } 22 } 23 24 public class DirectMessageItem 25 { 26 public string Username { get; set; } 27 public string Message { get; set; } 28 } 29 30 public class DirectMessageViewModel 31 { 32 public ReactiveProperty<AccountData> Account { get; } = new(); 33 public ReactiveCollection<DirectMessageItem> MessageInfos { get; } = new(); 34 public ReactiveCommand<string> SendCommand { get; } = new(); 35 public ReactiveProperty<bool> IsChecked { get; } = new(true); 36 37 public DirectMessageViewModel() 38 { 39 Account.Value = new() { Username = "dekaribon", }; 40 MessageInfos.Add(new() { Username = "dekaribon", Message = "aaa", }); 41 MessageInfos.Add(new() { Username = "TN8001", Message = "bbb", }); 42 43 SendCommand.Subscribe(message => 44 { 45 MessageInfos.Add(new() 46 { 47 Username = Account.Value.Username, 48 Message = message, 49 }); 50 }); 51 52 // アカウントチェンジ(不自然なチェンジだが、入れ替わりのテスト 53 IsChecked.Subscribe(x => 54 { 55 Account.Value = x ? new() { Username = "dekaribon", } 56 : new() { Username = "TN8001", }; 57 }); 58 } 59 } 60 61 public partial class MainWindow : Window 62 { 63 public MainWindow() => InitializeComponent(); 64 } 65}

以降は質問には関係ないんですが、コードを書いていて不思議に思ったことです。

あるSNSのアカウントごとにAPIを使用してダイレクトメッセージをLINE風に表示しようとしています。

AccountData.Usernameが自分のユーザー名、DirectMessageItem.Usernameが相手のユーザー名になります。

私が理解できていないだけかもしれませんが、逆じゃないですか?
「アカウントごと」というのは、DirectMessageViewModelごとという意味ですよね?
DirectMessageViewModelのリストがあり、自分<->Aさん・自分<->Bさん等になるんですよね?
自分と相手しかいないのであれば、Account.Usernameに自明な自分より相手の名前があったほうが便利そうですが(それとも最初から複垢想定?^^;

AccountReactivePropertyなのも「あれ?」と思いました。
変更される時があるということですかね?(DirectMessageViewModelは一つで使いまわす設計?)

それを逆手にとって、回答コードは入れ替わりのテストができたのですが^^;

あとThemeAssist.Theme="Dark"の当て方はあっているんでしょうか?
回答コードだとListBoxの選択が見えない(これは結果OKっぽい)のと、スクロールバーの色が見えなくなりました^^;

投稿2021/06/24 22:14

編集2023/08/14 09:53
TN8001

総合スコア9321

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

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

dekaribon

2021/06/25 04:12

回答ありがとうございます。 コードの省略は失礼しました。 以後気をつけます。 MultiBindingとコンバータを使うんですね。 こんな方法があったとは、勉強になります。 複数アカウント想定で同じviewmodelにアカウントのコレクションがあります。 それをdatagridにバインドして、選択されたものがAccountになるという感じです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問