1

使用可能なスペースの量に基づいてレイアウトを変更し、ボタン自体を小さくするようにスタイル設定されたボタンを作成しようとしています。

これらのボタンには、常に画像とテキストブロックを含むスタックパネルがあります。私は、これらのボタンに3〜4の異なるスタイルを定義できるようにすることを目指しており、それぞれが異なるボタンサイズになります。

ボタンの画像ごとに、解像度が異なる場合は4つのバージョンがあります。16、32、48、64。これらの画像は異なるフォルダに保存されます。つまり、Images \ Icons \ 16\Add.pngおよびImages\Icons \ 32\Add.pngです。これらの画像は両方とも同じですが、サイズが異なります。複数のサイズを使用することを選択したのは、1つの画像を使用してそのサイズを拡大縮小すると、画像がかなりぼやけてしまうことがわかったためです。

さまざまなサイズの画像を簡単に選択できるように、画像ソースをバインドするときに使用するコンバーターを作成しました。

class ImagePathResolutionConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        Image sender = (Image)value;
        int imageSize = (parameter != null) ? (parameter is int) ? (int)parameter : (parameter is string) ? Int32.Parse((string)parameter) : 16 : 16;
        Uri returnImage = new Uri(String.Format(@"Images\Icons\{0}\{1}", imageSize, sender.Tag as string), UriKind.Relative);
        return returnImage;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }

}

バインディングは次のようになります。

<Setter Property="Source" 
        Value="{Binding ., 
                Converter={StaticResource ImagePathResolutionConverter}, 
                RelativeSource={RelativeSource Self}, 
                ConverterParameter='16'}" 
/>

この設定を使用すると、ConverterParameterに16、32、48、または64を渡すことができ、適切な画像パスが返されます。

さて、この例では、2つのスタイルがあります。

大:

<!-- Big Button Container Style -->
<Style TargetType="Button" x:Key="MultiResButton_Big">
    <Setter Property="HorizontalAlignment" Value="Left" />
    <Setter Property="VerticalAlignment" Value="Top" />
    <Style.Resources>
        <!-- Button.StackPanel Style -->
        <Style TargetType="StackPanel">
            <Setter Property="Orientation" Value="Vertical" />
            <Style.Resources>
                <!-- Button.StackPanel.Image Style -->
                <Style TargetType="Image">
                    <Setter Property="Stretch" Value="None" />
                    <Setter Property="Margin" Value="5 2 5 0" />
                    <Setter Property="Source" Value="{Binding ., Converter={StaticResource ImagePathResolutionConverter}, RelativeSource={RelativeSource Self}, ConverterParameter='32'}" />
                </Style>
                <!-- Button.StackPanel.TextBlock Style -->
                <Style TargetType="TextBlock">
                    <Setter Property="Margin" Value="5 0 5 2" />
                </Style>
            </Style.Resources>
        </Style>
    </Style.Resources>
</Style>

...そして小さい

<!-- Small Button Container Style -->
<Style TargetType="Button" x:Key="MultiResButton_Small">
    <Setter Property="HorizontalAlignment" Value="Left" />
    <Setter Property="VerticalAlignment" Value="Top" />
    <Style.Resources>
        <!-- Button.StackPanel Style -->
        <Style TargetType="StackPanel">
            <Setter Property="Orientation" Value="Horizontal" />
            <Style.Resources>
                <!-- Button.StackPanel.Image Style -->
                <Style TargetType="Image">
                    <Setter Property="Stretch" Value="None" />
                    <Setter Property="Margin" Value="5 2" />
                    <Setter Property="Source" Value="{Binding ., Converter={StaticResource ImagePathResolutionConverter}, RelativeSource={RelativeSource Self}, ConverterParameter='16'}" />
                </Style>
                <!-- Button.StackPanel.TextBlock Style -->
                <Style TargetType="TextBlock">
                    <Setter Property="Margin" Value="0 5 2 5" />
                </Style>
            </Style.Resources>
        </Style>
    </Style.Resources>
</Style>    

これらのボタンの1つのXAMLは次のとおりです。

<Button Style="{StaticResource ResourceKey=MultiResButton_Big}">
    <StackPanel>
        <Image Tag="Multi.png" />
        <TextBlock Text="Button Text" />
    </StackPanel>            
</Button>

現時点では、ボタンをどちらかまたはこれらに設定でき、結果は大きなボタンまたは小さなボタンになります。今、私は、いつどちらを使用するかを決定する方法と、プログラムでそれを行う方法を理解する必要があります。

私の見方では、2つのオプションがあります。両方のスタイルを1つに組み合わせて、ある種のトリガーを使用するか、styleSelectorクラスを作成して、使用するスタイルを選択させます。

私の問題は、どのスタイルを使用するかをプログラムで決定する方法について途方に暮れていることです。ボタンがコンテナの表示範囲を超えて押されると、「RenderSize.Width」が0に設定されることがわかりました。私の問題は、5つのボタンがコンテナの表示範囲外にある場合、小さいスタイルを使用するように5を設定しても効果がないことです...作成するには、他の表示されるボタンにも小さいサイズを使用する必要があります。境界の外にある5人のための部屋。

コンテナ内のすべてのボタンのスタイルを設定できれば幸いです...1つのボタンがrenderSize.Width=0の瞬間に、すべての兄弟ボタンをスタイルサイズの小さいサイズにノックダウンします...

私が試みていることは可能でさえありますか?すべての子コントロールのレンダリングをオーバーライドするには、カスタムコンテナを作成する必要がありますか?できればそれは避けたいのですが...他に考えられる方法はありません...

私が達成しようとしていることの例として、WordまたはExcel 2007/2010を開き、ウィンドウのサイズをゆっくりと変更して小さくします。あなたがそうするように、リボンのボタンはより多くのスペースを作るために「縮小」します。

私が正しい方向からこれに取り組んでいるかどうかについての考えをいただければ幸いです。

4

1 に答える 1

0

2番目のコンバーターを使用してスタイルをバインドできます。

2つの値、ActualWidthと計算の基になる要素を受け取るIMultiValueConverterを作成します(私の例では、Windowを使用しています)。

class ImageButtonStyleSelectorConverter : IMultiValueConverter
{
    #region IMultiValueConverter Members

    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        Double actualWidth = values[0] as Double? ?? 0;
        FrameworkElement element = values[1] as FrameworkElement;

        if (element != null)
        {
            // perform calculations and return button size (using even/odd for illustration purposes)
            if (element.Width % 2 == 0)
            {
                return element.Resources["MultiResButton_Small"];
            }
            else
            {
                return element.Resources["MultiResButton_Big"];
            }
        }
        return Binding.DoNothing;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }

    #endregion
}

次に、ボタンを変更して、コンバーターを使用してスタイルを選択します。

        <Button>
            <Button.Style>
                <MultiBinding Converter="{StaticResource ImageButtonStyleSelectorConverter}"
                              FallbackValue="{StaticResource MultiResButton_Big}">
                    <Binding RelativeSource="{RelativeSource AncestorType=Window, Mode=FindAncestor}" Path="ActualWidth"/>
                    <Binding RelativeSource="{RelativeSource AncestorType=Window, Mode=FindAncestor}" Path="."/>
                </MultiBinding>
            </Button.Style>
            <StackPanel>
                <Image Tag="Multi.png" />
                <TextBlock Text="Button Text" />
            </StackPanel>
        </Button>

FallbackValueを追加したのは、そうしないと、デザインビューからどちらのスタイルも表示されなかったためです。

于 2012-04-13T18:04:49.413 に答える