2

私は、正方形である必要があり、与えられたスペースをできるだけ埋める必要があるユーザーコントロールを設計しています(コンテキストを与えるために、これはチェックボードです)。

私のユーザーコントロールは次のようになります。

<Grid>
    <!-- My 8 lines / colums, etc. , sized with "1*" to have equal lines -->
</Grid>

ここで、「このグリッドは、どの部屋を拡張する必要があるかに関係なく、正方形でなければなりません」と簡単に言いたいと思います。

無駄に解決策を試しました:

  1. 実際には行と列の名前が追加されているため、を使用できませんUniformGrid。そのため、先頭のヘッダーの行と列のサイズが異なります。

  2. 私がそれを使用するViewboxUniform、すべてが台無しになります。

  3. クラシックを使ってみました

    <Grid Height="{Binding RelativeSource={RelativeSource Self}, Path=Width}"> ... </Grid>
    

ただし、プロパティを手動で設定した場合にのみ機能しWidthます。それ以外の場合、この制約は無視されます。

結論

私は考えがわからないので、このコントロールはさまざまな場所(テンプレート、ゲームなど)で使用される可能性があるため、手動で設定Width/手動で設定することは避けたいと思います。HeightListItem


提案からの解決策:

いくつかのコードビハインドで解決策が利用可能です。XAMLのみのソリューションは見つかりませんでした。

グリッドは次のようになりました。

<Grid SizeChanged="Board_FullControlSizeChanged">...</Grid>

そして、イベントハンドラーは次のとおりです。

private void Board_FullControlSizeChanged(object sender, SizeChangedEventArgs args)
{
    double size = Math.min (args.NewSize.Height, args.NewSize.Width);
    ((Grid)sender).Width = size;
    ((Grid)sender).Height = size;
}
4

5 に答える 5

3

最初にバインディングを変更しようとしましたが、が最上位の要素である場合はActualWidthまだ機能せず、場合によっては、使用可能なサイズを超えてコントロールを拡張することになりました。Gridしたがって、必要な出力を取得する他の方法をいくつか試しました。

おそらくこれに対処する2つの方法があります:

これはビュー関連の問題であるため(MVVMを壊さず、正方形のフォーメーションを維持し、コードビハインドが少しあれば問題ない場合は、次のようなことができます)

private void OnSizeChanged(object sender, SizeChangedEventArgs e) {
  double minNewSizeOfParentUserControl = Math.Min(e.NewSize.Height, e.NewSize.Width);
  mainGrid.Width = minNewSizeOfParentUserControl;
  mainGrid.Height = minNewSizeOfParentUserControl;
}

xamlで、メインのトップレベルグリッドに「mainGrid」という名前を付け、UserControlサイズ変更されたイベントハンドラーをGridそれ自体ではなく上記の関数にアタッチします。

ただし、何らかの理由でコードビハインドが完全に嫌いな場合は、もう少し凝って、次のような動作を作成できます。

public class GridSquareSizeBehavior : Behavior<Grid> {
  private UserControl _parent;

  protected override void OnAttached() {
    DependencyObject ucParent = AssociatedObject.Parent;
    while (!(ucParent is UserControl)) {
      ucParent = LogicalTreeHelper.GetParent(ucParent);
    }
    _parent = ucParent as UserControl;
    _parent.SizeChanged += SizeChangedHandler;
    base.OnAttached();
  }

  protected override void OnDetaching() {
    _parent.SizeChanged -= SizeChangedHandler;
    base.OnDetaching();
  }

  private void SizeChangedHandler(object sender, SizeChangedEventArgs e) {
    double minNewSizeOfParentUserControl = Math.Min(e.NewSize.Height, e.NewSize.Width);
    AssociatedObject.Width = minNewSizeOfParentUserControl;
    AssociatedObject.Height = minNewSizeOfParentUserControl;
  }
}

動作については、xamlは次のようになります。

  <Grid>
    <i:Interaction.Behaviors>
      <local:GridSquareSizeBehavior />
    </i:Interaction.Behaviors>
  </Grid>

スヌープでこれら2つの方法をテストし、拡大/縮小しながら正方形のサイズを維持しました。核心の両方の方法が同じロジックを使用していることに注意してください(簡単なモックアップ)。ロジックを更新して幅が変更されたときにのみ高さを更新し、その逆の場合は両方ではなく、キャンセルすると、パフォーマンスが向上する可能性があります必要がなければ、すべて一緒にサイズ変更します

于 2013-03-24T22:09:10.857 に答える
1

グリッドをViewBoxに配置してみてください:http://msdn.microsoft.com/en-us/library/system.windows.controls.viewbox.aspx

これが私が思いついたコードサンプルです:

ユーザーコントロール:

<UserControl x:Class="StackOverflow.CheckBoard"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Viewbox>
        <Grid Background="Red" Height="200" Width="200">
            <Grid.RowDefinitions>
                <RowDefinition/>
                <RowDefinition/>
                <RowDefinition/>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <Button Content="testing" Grid.Row="0"/>
            <Button Content="testing" Grid.Row="1"/>
            <Button Content="testing" Grid.Row="2"/>
        </Grid>
    </Viewbox>
</UserControl>

そしてメインウィンドウ:

<Window x:Class="StackOverflow.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:StackOverflow"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <local:AllNoneCheckboxConverter x:Key="converter"/>
    </Window.Resources>
    <Grid>
        <StackPanel>
            <local:CheckBoard MaxWidth="80"/>
        </StackPanel>
    </Grid>
</Window>

このビューボックスが行うことは、指定されたスペースに合わせてコントロールをスケーリングすることです。ビューボックス内のグリッドは正方形であるため、グリッドは常に正方形のままになります。MainWindowで使用したMaxWidthプロパティを試してみてください。

于 2013-03-25T08:39:27.930 に答える
0

の代わりにHeightプロパティをバインドできます:ActualWidthWidth

<Grid Height="{Binding ActualWidth, RelativeSource={RelativeSource Self}}">
    ...
</Grid>

ただし、より良い解決策は、ビューボックスを使用することです。それが「すべてを台無しにする」ことを回避する秘訣は、幅と高さの(賢明な)等しい値を定義することによって子を正方形にすることです。

<Viewbox>
    <Grid Width="500" Height="500">
        ...              
    </Grid>
</Viewbox>
于 2013-03-24T21:55:19.890 に答える
0

自分に合った場所(通常はコンストラクターまたはOnAttached())で登録します。

SizeChanged += Square;

これでサイズを処理します:

private void Square(object sender, SizeChangedEventArgs e)
{
    if (e.HeightChanged) Width = e.NewSize.Height;
    else if (e.WidthChanged) Height = e.NewSize.Width;
}
于 2018-08-08T19:10:20.853 に答える
0

親コントロールのサイズ変更イベント内から含まれるコントロールのマージンを設定することで、これを解決しました。私の場合、MainGrid(メインウィンドウ全体)と呼ばれる標準のグリッドコントロール内にSudokuBoardと呼ばれる「数独グリッド」ユーザーコントロールがあり、次のコードのみが必要です。

    private void MainGrid_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        double verticalMargin = Math.Max((e.NewSize.Height - e.NewSize.Width)*0.5, 0.0);
        double horizontalMargin = Math.Max((e.NewSize.Width - e.NewSize.Height)*0.5, 0.0);
        SudokuBoard.Margin = new Thickness(horizontalMargin, verticalMargin, horizontalMargin, verticalMargin); 
    }
于 2021-12-29T09:35:57.120 に答える