web-dev-qa-db-ja.com

ウィンドウの高さと幅へのバインドに関する問題

ウィンドウの高さと幅をビューモデルのプロパティにバインドしようとすると、問題が発生します。これが問題を説明する小さなサンプルアプリです。これはapp.xaml.xsのコードです

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
       base.OnStartup(e);
        MainWindow mainWindow = new MainWindow();
        MainWindowViewModel mainWindowViewModel = new MainWindowViewModel();
        mainWindow.DataContext = mainWindowViewModel;
        mainWindow.Show();
    }
}

これはMainWindow.xamlです。

<Window x:Class="TestApp.MainWindow"
        xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml"
        Height="{Binding WindowHeight}" 
        Width="{Binding WindowWidth}"
        BorderThickness="{Binding WindowBorderThickness}">
</Window>

そしてこれはビューモデルです:

public class MainWindowViewModel
{
    public int WindowWidth { get { return 100; } }
    public int WindowHeight { get { return 200; } }
    public int WindowBorderThickness { get { return 8; } }
}

プログラムが開始されると、WindowHeightおよびWindowBorderThickness(WindowWidthではなく)のゲッターが呼び出されるため、ウィンドウの高さと枠線は正しく設定されますが、幅は設定されません。

次に、すべてのプロパティに対してPropertyChangedをトリガーするボタンを追加して、ビューモデルが次のようになるようにします。

public class MainWindowViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public void TriggerPropertyChanges()
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs("WindowWidth"));
            PropertyChanged(this, new PropertyChangedEventArgs("WindowHeight"));
            PropertyChanged(this, new PropertyChangedEventArgs("WindowBorderThickness"));
        }

    }

    public ICommand ButtonCommand { get { return new RelayCommand(delegate { TriggerPropertyChanges(); }); } }

    public int WindowWidth { get { return 100; } }
    public int WindowHeight { get { return 200; } }
    public int WindowBorderThickness { get { return 8; } }
}

ボタンをクリックすると、WindowBorderThicknessのゲッターが呼び出されますが、WindowWidthおよびWindowHeightのゲッターは呼び出されません。それはすべて私にとって非常に奇妙で矛盾しているように思えます。何が欠けていますか?

25
D.H.

自分の質問に答えてみます。バインディングは機能していますが、レイアウトシステムが要求していることを本当に確信できません。ウィンドウのWidthプロパティ。

から [〜#〜] msdn [〜#〜]

この要素が他の要素内の子要素である場合、このプロパティを値に設定することは、実際には推奨値にすぎません。レイアウトシステムと親要素の特定のレイアウトロジックは、レイアウトプロセス中に非バインド入力として値を使用します。実際には、FrameworkElementはほとんどの場合、何か他の子要素です。ウィンドウの高さを設定した場合でも。 (ウィンドウの場合、その値は、基になるアプリケーションモデルが、アプリケーションをホストするHwndを作成する基本的なレンダリングの仮定を確立するときに使用されます。)

機能しているように見える解決策は、WindowWidthプロパティをMinWidthとMaxWidth、およびWidthにバインドすることです。これらのうちの1つは、少なくとも上記で使用していたテストシナリオでは取得されます。

11
D.H.

双方向バインディングを使用してみてください、それは私のために働きました:

Width="{Binding Path=xExt, Mode=TwoWay}"
43
Gregory Seront

同じ問題があり、高さまたは幅が最初にxamlで記述されているかどうかに依存することに気付きました。高さが最初の場合、Bindingはその高さでのみ機能し、その逆も同様です。解決策は、バインディングモードを 'TwoWay'に設定することでした。私が作成したプロジェクトは、MS Studio 2010と.NET 4.0でした。

10
VNedyalkov

さらに、SizeToContent="WidthAndHeight"MinHeightおよびMinWidthを使用するため、MaxHeightおよびMaxWidthに追加の呼び出しは必要ありません。

5
manu

OK、

同じ問題があり、XAMLを介してビューのモデルにウィンドウのサイズ(最小、最大、標準)を正しくバインドできませんでした。

理由はわかりませんが、XAMLではなくコードでバインドすれば、すべてのバインディングを問題なく達成できます。

これが機能した私のC#コードです:

this.SetBinding(Window.WidthProperty, new Binding("Width") { Source = MyViewModel, Mode=BindingMode.TwoWay });
this.SetBinding(Window.HeightProperty, new Binding("Height") { Source = MyViewModel, Mode=BindingMode.TwoWay });
this.SetBinding(Window.MaxWidthProperty, new Binding("MaxWidth") { Source = MyViewModel });
this.SetBinding(Window.MaxHeightProperty, new Binding("MaxHeight") { Source = MyViewModel });
this.SetBinding(Window.MinWidthProperty, new Binding("MinWidth") { Source = MyViewModel });
this.SetBinding(Window.MinHeightProperty, new Binding("MinHeight") { Source = MyViewModel });

コードでのみ機能し、XAMLでは機能しないのは奇妙です。 "Mode = BindingMode.TwoWay"を指定する必要がある通常のディメンションではなく、mminとMaxディメンションのデフォルトでTwoWayをバインドするのはさらに奇妙です。

Microsoftがこれについて修正しなければならないバグがあるはずです...

5
user2883257

MinWidthおよびMinHeightへのバインドは正しいです。また、ダイナミックがウィンドウのサイズを拡大または縮小する場合、MaxWidthおよびMaxHeightにバインドする必要があります。

1
John Mao

特定の実装についてはわかりませんが、役に立つかもしれない例を書いています。

XAML

<Window x:Name="MainWindow"
    x:Class="MainWindow"
    xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml"
    Title="MainWindow" 
    MinWidth="200"
    MinHeight="100"
    Width="{Binding ElementName=MainWindow, Path=WindowWidth}"
    Height="{Binding ElementName=MainWindow, Path=WindowHeight}">
    <Grid>
        <Slider 
            x:Name="slWidth" 
            Value="{Binding ElementName=MainWindow, Path=WindowWidth, Mode=TwoWay}"
            Minimum="200"
            Maximum="1600"
            Height="23" HorizontalAlignment="Left" Margin="56,22,0,0" VerticalAlignment="Top" Width="61" />
        <Label 
            Content="Width" 
            Height="28" 
            HorizontalAlignment="Left" 
            Margin="12,22,0,0" 
            Name="Label1" 
            VerticalAlignment="Top" />
        <Slider 
            x:Name="slHeight" 
            Value="{Binding ElementName=MainWindow, Path=WindowHeight, Mode=TwoWay}"
            Minimum="100"
            Maximum="800"
            Height="23" HorizontalAlignment="Left"  VerticalAlignment="Top" Width="61" Margin="56,51,0,0" />
        <Label 
            Content="Height" 
            Height="28" 
            HorizontalAlignment="Left"              
            VerticalAlignment="Top" Margin="12,46,0,0" />
    </Grid>
</Window>

コード

Class MainWindow

    Public Shared ReadOnly WindowWidthProperty As DependencyProperty = _
                           DependencyProperty.Register("WindowWidth", _
                           GetType(Integer), GetType(MainWindow), _
                           New FrameworkPropertyMetadata(Nothing))

    Public Shared ReadOnly WindowHeightProperty As DependencyProperty = _
                         DependencyProperty.Register("WindowHeight", _
                         GetType(Integer), GetType(MainWindow), _
                         New FrameworkPropertyMetadata(Nothing))

    Public Property WindowWidth As Integer
        Get
            Return CInt(GetValue(WindowWidthProperty))
        End Get
        Set(ByVal value As Integer)
            SetValue(WindowWidthProperty, value)
        End Set
    End Property

    Public Property WindowHeight As Integer
        Get
            Return CInt(GetValue(WindowHeightProperty))
        End Get
        Set(ByVal value As Integer)
            SetValue(WindowHeightProperty, value)
        End Set
    End Property


End Class

C#コード

public readonly DependencyProperty WindowWidthProperty = DependencyProperty.Register("WindowWidth", typeof(Double), typeof(MainWindow), new FrameworkPropertyMetadata());
public readonly DependencyProperty WindowHeightProperty = DependencyProperty.Register("WindowHeight", typeof(Double), typeof(MainWindow), new FrameworkPropertyMetadata());

public double WindowWidth {
    get { return Convert.ToDouble(this.GetValue(WindowWidthProperty)); }
    set { this.SetValue(WindowWidthProperty, value); }
}

public double WindowHeight {
    get { return Convert.ToDouble(this.GetValue(WindowHeightProperty)); }
    set { this.SetValue(WindowHeightProperty, value); }
}
0
Drake