web-dev-qa-db-ja.com

ColumnDefinitionの幅またはRowDefinitionの高さをデータバインドするにはどうすればよいですか?

WPFのView-Model-ViewModelパターンの下で、グリッドコントロールのさまざまな定義の高さと幅をデータバインドしようとしています。これにより、GridSplitterを使用した後にユーザーが設定した値を保存できます。ただし、通常のパターンはこれらの特定のプロパティでは機能しないようです。

注:Googleが失敗し、自分で解決する必要があったため、これを参照用の質問として投稿しています。私自身の回答に従ってください。

33
Nidonocu

私が発見したいくつかの落とし穴がありました:

  1. XAMLではdoubleのように見える場合がありますが、* DefinitionのHeightまたはWidthの実際の値は 'GridLength'構造体です。
  2. GridLengthのすべてのプロパティは読み取り専用であるため、変更するたびに新しいプロパティを作成する必要があります。
  3. WPFの他のすべてのプロパティとは異なり、WidthとHeightはデフォルトでデータバインディングモードを「TwoWay」に設定しないため、手動で設定する必要があります。

したがって、私は次のコードを使用しました:

private GridLength myHorizontalInputRegionSize = new GridLength(0, GridUnitType.Auto)
public GridLength HorizontalInputRegionSize
{
    get
    {
        // If not yet set, get the starting value from the DataModel
        if (myHorizontalInputRegionSize.IsAuto)
            myHorizontalInputRegionSize = new GridLength(ConnectionTabDefaultUIOptions.HorizontalInputRegionSize, GridUnitType.Pixel);
        return myHorizontalInputRegionSize;
    }
    set
    {
        myHorizontalInputRegionSize = value;
        if (ConnectionTabDefaultUIOptions.HorizontalInputRegionSize != myHorizontalInputRegionSize.Value)
        {
            // Set the value in the DataModel
            ConnectionTabDefaultUIOptions.HorizontalInputRegionSize = value.Value;
        }
        OnPropertyChanged("HorizontalInputRegionSize");
    }
}

そしてXAML:

<Grid.RowDefinitions>
    <RowDefinition Height="*" MinHeight="100" />
    <RowDefinition Height="Auto" />
    <RowDefinition Height="{Binding Path=HorizontalInputRegionSize,Mode=TwoWay}" MinHeight="50" />
</Grid.RowDefinitions>
20
Nidonocu

次のようにIValueConverterを作成します。

public class GridLengthConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        double val = (double)value;
        GridLength gridLength = new GridLength(val);

        return gridLength;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        GridLength val = (GridLength)value;

        return val.Value;
    }
}

その後、バインディングでコンバーターを利用できます。

<UserControl.Resources>
    <local:GridLengthConverter x:Key="gridLengthConverter" />
</UserControl.Resources>
...
<ColumnDefinition Width="{Binding Path=LeftPanelWidth, 
                                  Mode=TwoWay,
                                  Converter={StaticResource gridLengthConverter}}" />
39
Greg Sansom

もう1つの可能性は、GridLengthintの間の変換を提起したため、IValueConverterを作成し、それをWidthにバインドするときに使用することです。 IValueConvertersは、ConvertTo()メソッドとConvertBack()メソッドの両方を備えているため、双方向バインディングも処理します。

4
Joel B Fant

最も簡単な解決策は、これらのプロパティに文字列設定を使用することです。これにより、WPFは、GridLengthConverterを使用して、追加の作業なしでそれらを自動的にサポートします。

4
JustinMichel