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

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

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

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

XAML

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

WPF

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

Q&A

解決済

2回答

2016閲覧

ウィンドウ起動後のコントロールのサイズをViewModelに渡したい

kubo1216

総合スコア4

C#

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

XAML

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

WPF

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

1グッド

0クリップ

投稿2023/02/18 22:58

実現したいこと

WPFのアプリケーションでViewModelにコントロールのサイズを渡したいです。
SizeChangedイベントを利用してSizeを渡すことには成功しました。
しかし、ウィンドウの起動時にSizeChagedイベントは発生しません。
したがって起動後、ウィンドウのサイズを手動でちょこっと変えてあげなければなりません。
この起動後のコントロールのサイズを渡す良い方法はないでしょうか。

よろしくお願いします。
※一度ViewModelに渡してしまえばその値を保存して使用します。

前提

ここに質問の内容を詳しく書いてください。
Visual Studio 2022
C#(.Net 6)
Prism.Dryloc (8.1.97)
ReactiveProperty.WPF (9.0.0)

該当のソースコード

C#

1// MainWindowViewModel.cs 2using Prism.Mvvm; 3using Reactive.Bindings; 4using System; 5using System.Windows; 6 7namespace BlankApp1.ViewModels 8{ 9 public class MainWindowViewModel : BindableBase 10 { 11 public MainWindowViewModel() 12 { 13 SizeChangedCommand.Subscribe(size => 14 { 15 // size.Width 16 // size.Heightを利用したい 17 }); 18 } 19 public ReactiveCommand<Size> SizeChangedCommand { get; } = new(); 20 } 21} 22

xml

1<!-- MainWindow.xaml --> 2<Window x:Class="BlankApp1.Views.MainWindow" 3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5 xmlns:i="http://schemas.microsoft.com/xaml/behaviors" 6 xmlns:prism="http://prismlibrary.com/" 7 prism:ViewModelLocator.AutoWireViewModel="True" 8 Title="{Binding Title}" Height="350" Width="525" > 9 <Grid> 10 <Rectangle Stroke="Aqua" StrokeThickness="10" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"> 11 <i:Interaction.Triggers> 12 <i:EventTrigger EventName="SizeChanged"> 13 <i:InvokeCommandAction Command="{Binding SizeChangedCommand}" EventArgsParameterPath="NewSize"/> 14 </i:EventTrigger> 15 </i:Interaction.Triggers> 16 </Rectangle> 17 </Grid> 18</Window> 19 20
TN8001😄を押しています

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

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

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

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

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

Zuishin

2023/02/18 23:21

「起動」(表示?)したイベントを使えばいいのでは?
kubo1216

2023/02/19 01:04

ありがとうございます! おっしゃる通りLoadedイベントを利用して解決できました。 解決方法を入力して質問を閉じようと思います。
guest

回答2

0

しかし、ウィンドウの起動時にSizeChagedイベントは発生しません。

コードビハインドなら来るんですけど、確かになぜか来ないですね...
Interaction.Triggersの?)タイミング的な問題だとは思うんですが、いろいろ試しても解決できませんでした。

コードビハインドなら来るのはわかっているので、雑にビヘイビアにしました。
ActualWidthActualHeightなので、もちろん設定はできません(OneWayToSource相当)

xml

1<Window 2 x:Class="Qfpwwvzt0zl808x.Views.MainWindow" 3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5 xmlns:i="http://schemas.microsoft.com/xaml/behaviors" 6 xmlns:prism="http://prismlibrary.com/" 7 xmlns:views="clr-namespace:Qfpwwvzt0zl808x.Views" 8 Title="{Binding Title}" 9 Width="{Binding WindowWidth, Mode=TwoWay}" 10 Height="{Binding WindowHeight, Mode=TwoWay}" 11 prism:ViewModelLocator.AutoWireViewModel="True"> 12 <Grid> 13 <Rectangle 14 SizeChanged="Rectangle_SizeChanged" 15 Stroke="Aqua" 16 StrokeThickness="10"> 17 <i:Interaction.Behaviors> 18 <views:ActualSizeBehavior ActualSize="{Binding RectSize}" /> 19 </i:Interaction.Behaviors> 20 </Rectangle> 21 </Grid> 22</Window>

cs

1using System.Diagnostics; 2using System.Windows; 3using Microsoft.Xaml.Behaviors; 4 5namespace Qfpwwvzt0zl808x.Views; 6 7 8public partial class MainWindow : Window 9{ 10 public MainWindow() => InitializeComponent(); 11 12 private void Rectangle_SizeChanged(object sender, SizeChangedEventArgs e) 13 => Debug.WriteLine($"Rectangle_SizeChanged: {e.NewSize}"); 14} 15 16public class ActualSizeBehavior : Behavior<FrameworkElement> 17{ 18 public Size ActualSize { get => (Size)GetValue(ActualSizeProperty); set => SetValue(ActualSizeProperty, value); } 19 public static readonly DependencyProperty ActualSizeProperty 20 = DependencyProperty.Register(nameof(ActualSize), typeof(Size), typeof(ActualSizeBehavior), 21 new FrameworkPropertyMetadata(new Size(), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault)); 22 23 protected override void OnAttached() => AssociatedObject.SizeChanged += AssociatedObject_SizeChanged; 24 protected override void OnDetaching() => AssociatedObject.SizeChanged -= AssociatedObject_SizeChanged; 25 26 private void AssociatedObject_SizeChanged(object sender, SizeChangedEventArgs e) 27 { 28 ActualSize = new Size(AssociatedObject.ActualWidth, AssociatedObject.ActualHeight); 29 } 30}

cs

1using System.ComponentModel; 2using System.Diagnostics; 3using System.Windows; 4using Prism.Mvvm; 5 6namespace Qfpwwvzt0zl808x.ViewModels; 7 8 9public class MainWindowViewModel : BindableBase 10{ 11 public string Title { get => _title; set => SetProperty(ref _title, value); } 12 private string _title = "Prism Application"; 13 14 public double WindowWidth { get => _WindowWidth; set => SetProperty(ref _WindowWidth, value); } 15 private double _WindowWidth; 16 17 public double WindowHeight { get => _WindowHeight; set => SetProperty(ref _WindowHeight, value); } 18 private double _WindowHeight; 19 20 public Size RectSize { get => _RectSize; set => SetProperty(ref _RectSize, value); } 21 private Size _RectSize; 22 23 24 public MainWindowViewModel() 25 { 26 // ファイルから読んだりするテイ 27 WindowWidth = 525; 28 WindowHeight = 350; 29 30 PropertyChanged += MainWindowViewModel_PropertyChanged; 31 } 32 33 private void MainWindowViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e) 34 { 35 if (e.PropertyName == nameof(RectSize)) Debug.WriteLine($"{nameof(RectSize)}: {RectSize}"); 36 37 if (e.PropertyName == nameof(WindowWidth)) Debug.WriteLine($"{nameof(WindowWidth)}: {WindowWidth}"); 38 if (e.PropertyName == nameof(WindowHeight)) Debug.WriteLine($"{nameof(WindowHeight)}: {WindowHeight}"); 39 } 40}

Loadedイベントでコントロールの表示時のWidthとHeightを取得して解決しました。
var view = e.Source as Views.MainWindow;

MainWindowのサイズ保存・復元が目的なら、単純にWidthHeightにバインドで十分です。

投稿2023/02/19 01:46

編集2023/02/19 01:49
TN8001

総合スコア9313

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

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

TN8001

2023/02/19 01:46

解決されたようですが^^;
kubo1216

2023/02/19 01:59

回答いただきありがとうございます。 ビヘイビアの作り方とかよくわかってない部分も多いのでとても参考になります。 Width、HeightにバインドするとNanが入らないですか...?
TN8001

2023/02/19 03:55 編集

> ビヘイビアの作り方とかよくわかってない部分も多いのでとても参考になります。 ビヘイビアと大仰な名前がついていますが、見た通りコードビハインドを切り出しているだけにすぎません^^; 例えば「Windowのサイズ保存」が目的なら、ビヘイビア内でファイル入出力を書いてしまってもいいわけです。 ViewModelに渡したいということなので、(バインドするために)依存関係プロパティ(DependencyProperty)もあってさらに難解に見えてしまっています。 (特に開発初期は)厳格なMVVMにこだわらず、適度にコードビハインドも使っていいと思います(後から変更も可能ですし) > Width、HeightにバインドするとNanが入らないですか...? この場合のRectangleであれば、Double.NaNですね。 kubo1216さんの回答ではWindow.Loadedに変わっていたので、「Windowのサイズ保存が目的であれば...」という蛇足です^^; 任意のコントロールのサイズが欲しいなら、ActualWidth・ActualHeightを見るしかないですね。
kubo1216

2023/02/23 04:47

返信が遅くなりすみません。 > 厳格なMVVMにこだわらず、適度にコードビハインドも使っていいと思います 確かにコードビハインドで書いたら良かったかもしれません... > Window.Loadedに変わっていたので、「Windowのサイズ保存が目的であれば...」という蛇足です^^; > 任意のコントロールのサイズが欲しいなら、ActualWidth・ActualHeightを見るしかないですね。 なるほど、分かりました。 親切に教えていただきありがとうございました。
guest

0

自己解決

Loadedイベントでコントロールの表示時のWidthとHeightを取得して解決しました。

C#

1// MainWindowViewModel.cs 2 public class MainWindowViewModel : BindableBase 3 { 4 public MainWindowViewModel() 5 { 6 SizeChangedCommand.Subscribe(size => 7 { 8 9 }); 10 11 // Loadedイベント用のコマンドを追加 12 LoadCommand.Subscribe(e => 13 { 14 var view = e.Source as Views.MainWindow; 15 //view.ActualWidth; 16 //view.ActualHeight; 17 }); 18 } 19 public ReactiveCommand<Size> SizeChangedCommand { get; } = new(); 20 public ReactiveCommand<RoutedEventArgs> LoadCommand { get; } = new(); 21 }

xml

1<!-- MainWindow.xaml --> 2<!-- Loadedイベントのイベントトリガーを追加 --> 3 <i:Interaction.Triggers> 4 <i:EventTrigger EventName="Loaded"> 5 <rp:EventToReactiveCommand Command="{Binding LoadCommand}"/> 6 </i:EventTrigger> 7 </i:Interaction.Triggers>

投稿2023/02/19 01:12

kubo1216

総合スコア4

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問