web-dev-qa-db-ja.com

WPF角丸コンテナーを作成するにはどうすればよいですか?

1ページのさまざまな場所に角を丸くする必要があるXBAPアプリケーションを作成しています。また、他の要素を配置するためのWPF角丸コンテナが必要です。誰が私たちがこれを最もうまく達成することができるかについての提案やサンプルコードを持っていますか?スタイルを使用するか、カスタムコントロールを作成しますか?

104
FarrEver

カスタムコントロールは必要ありません。コンテナを境界要素に配置するだけです。

<Border BorderBrush="#FF000000" BorderThickness="1" CornerRadius="8">
   <Grid/>
</Border>

<Grid/>を任意のレイアウトコンテナに置き換えることができます...

243
kobusb

これは最初の質問に対する答えではないことは知っていますが、多くの場合、作成したばかりの丸みを帯びた角の境界線の内側のコンテンツをクリップする必要があります。

Chris Cavanaghは、これを行うために excellent way を考案しました。

私はこれにいくつかの異なるアプローチを試みました...そして、私はこれが揺れると思います。

以下はxamlです。

<Page
    xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml"
    Background="Black"
>
    <!-- Rounded yellow border -->
    <Border
        HorizontalAlignment="Center"
        VerticalAlignment="Center"
        BorderBrush="Yellow"
        BorderThickness="3"
        CornerRadius="10"
        Padding="2"
    >
        <Grid>
            <!-- Rounded mask (stretches to fill Grid) -->
            <Border
                Name="mask"
                Background="White"
                CornerRadius="7"
            />

            <!-- Main content container -->
            <StackPanel>
                <!-- Use a VisualBrush of 'mask' as the opacity mask -->
                <StackPanel.OpacityMask>
                    <VisualBrush Visual="{Binding ElementName=mask}"/>
                </StackPanel.OpacityMask>

                <!-- Any content -->
                <Image Source="http://chriscavanagh.files.wordpress.com/2006/12/chriss-blog-banner.jpg"/>
                <Rectangle
                    Height="50"
                    Fill="Red"/>
                <Rectangle
                    Height="50"
                    Fill="White"/>
                <Rectangle
                    Height="50"
                    Fill="Blue"/>
            </StackPanel>
        </Grid>
    </Border>
</Page>
50
cplotts

私はこれを自分でしなければならなかったので、ここに別の答えを投稿すると思いました。

角の丸い境界線を作成する別の方法を次に示しますおよびその内部コンテンツをクリップします。これは、Clipプロパティを使用する簡単な方法です。 VisualBrushを避けたい場合はいいですね。

Xaml:

<Border
    Width="200"
    Height="25"
    CornerRadius="11"
    Background="#FF919194"
>
    <Border.Clip>
        <RectangleGeometry
            RadiusX="{Binding CornerRadius.TopLeft, RelativeSource={RelativeSource AncestorType={x:Type Border}}}"
            RadiusY="{Binding RadiusX, RelativeSource={RelativeSource Self}}"
        >
            <RectangleGeometry.Rect>
                <MultiBinding
                    Converter="{StaticResource widthAndHeightToRectConverter}"
                >
                    <Binding
                        Path="ActualWidth"
                        RelativeSource="{RelativeSource AncestorType={x:Type Border}}"
                    />
                    <Binding
                        Path="ActualHeight"
                        RelativeSource="{RelativeSource AncestorType={x:Type Border}}"
                    />
                </MultiBinding>
            </RectangleGeometry.Rect>
        </RectangleGeometry>
    </Border.Clip>

    <Rectangle
        Width="100"
        Height="100"
        Fill="Blue"
        HorizontalAlignment="Left"
        VerticalAlignment="Center"
    />
</Border>

コンバーターのコード:

public class WidthAndHeightToRectConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        double width = (double)values[0];
        double height = (double)values[1];
        return new Rect(0, 0, width, height);
    }
    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
13
cplotts

KobusbのボーダーコントロールソリューションのVB.Netコードベースの実装。 ButtonコントロールのListBoxを作成するために使用しました。 Buttonコントロールは、MEF拡張から作成されます。各拡張機能は、拡張機能の説明にMEFのExportMetaData属性を使用します。拡張機能はVisiFireチャートオブジェクトです。ユーザーは、ボタンのリストから選択されたボタンを押して、目的のチャートを実行します。

        ' Create a ListBox of Buttons, one button for each MEF charting component. 
    For Each c As Lazy(Of ICharts, IDictionary(Of String, Object)) In ext.ChartDescriptions
        Dim brdr As New Border
        brdr.BorderBrush = Brushes.Black
        brdr.BorderThickness = New Thickness(2, 2, 2, 2)
        brdr.CornerRadius = New CornerRadius(8, 8, 8, 8)
        Dim btn As New Button
        AddHandler btn.Click, AddressOf GenericButtonClick
        brdr.Child = btn
        brdr.Background = btn.Background
        btn.Margin = brdr.BorderThickness
        btn.Width = ChartsLBx.ActualWidth - 22
        btn.BorderThickness = New Thickness(0, 0, 0, 0)
        btn.Height = 22
        btn.Content = c.Metadata("Description")
        btn.Tag = c
        btn.ToolTip = "Push button to see " & c.Metadata("Description").ToString & " chart"
        Dim lbi As New ListBoxItem
        lbi.Content = brdr
        ChartsLBx.Items.Add(lbi)
    Next

Public Event Click As RoutedEventHandler

Private Sub GenericButtonClick(sender As Object, e As RoutedEventArgs)
    Dim btn As Button = DirectCast(sender, Button)
    Dim c As Lazy(Of ICharts, IDictionary(Of String, Object)) = DirectCast(btn.Tag, Lazy(Of ICharts, IDictionary(Of String, Object)))
    Dim w As Window = DirectCast(c.Value, Window)
    Dim cc As ICharts = DirectCast(c.Value, ICharts)
    c.Value.CreateChart()
    w.Show()
End Sub

<System.ComponentModel.Composition.Export(GetType(ICharts))> _
<System.ComponentModel.Composition.ExportMetadata("Description", "Data vs. Time")> _
Public Class DataTimeChart
    Implements ICharts

    Public Sub CreateChart() Implements ICharts.CreateChart
    End Sub
End Class

Public Interface ICharts
    Sub CreateChart()
End Interface

Public Class Extensibility
    Public Sub New()
        Dim catalog As New AggregateCatalog()

        catalog.Catalogs.Add(New AssemblyCatalog(GetType(Extensibility).Assembly))

        'Create the CompositionContainer with the parts in the catalog
        ChartContainer = New CompositionContainer(catalog)

        Try
            ChartContainer.ComposeParts(Me)
        Catch ex As Exception
            Console.WriteLine(ex.ToString)
        End Try
    End Sub

    ' must use Lazy otherwise instantiation of Window will hold open app. Otherwise must specify Shutdown Mode of "Shutdown on Main Window".
    <ImportMany()> _
    Public Property ChartDescriptions As IEnumerable(Of Lazy(Of ICharts, IDictionary(Of String, Object)))

End Class
2
BSalita

角丸長方形の境界線にボタンを配置しようとしている場合は、 msdnの例 をチェックアウトする必要があります。これは、テキストではなく問題の画像をグーグルで検索して見つけました。かさばる外側の長方形は(ありがたいことに)簡単に削除できます。

(ControlTemplateを変更したため)ボタンの動作を再定義する必要があることに注意してください。つまり、ControlTemplate.TriggersタグのTriggerタグ(Property = "IsPressed" Value = "true")を使用してクリックしたときのボタンの動作を定義する必要があります。これが私が失った時間を他の誰かに救うことを願っています:)

1
Daniel