단일 페이지의 다양한 위치에 둥근 모서리가 있어야하는 XBAP 응용 프로그램을 만들고 있으며 WPF 둥근 모서리 컨테이너를 사용하여 다른 요소를 배치하려고합니다. 누구든지 우리가 이것을 가장 잘 수행 할 수있는 방법에 대한 제안이나 샘플 코드가 있습니까? 스타일을 사용하거나 사용자 지정 컨트롤을 만들었습니까?
단일 페이지의 다양한 위치에 둥근 모서리가 있어야하는 XBAP 응용 프로그램을 만들고 있으며 WPF 둥근 모서리 컨테이너를 사용하여 다른 요소를 배치하려고합니다. 누구든지 우리가 이것을 가장 잘 수행 할 수있는 방법에 대한 제안이나 샘플 코드가 있습니까? 스타일을 사용하거나 사용자 지정 컨트롤을 만들었습니까?
답변:
사용자 지정 컨트롤이 필요하지 않고 테두리 요소에 컨테이너를 배치하기 만하면됩니다.
<Border BorderBrush="#FF000000" BorderThickness="1" CornerRadius="8">
<Grid/>
</Border>
<Grid/>
레이아웃 컨테이너로를 대체 할 수 있습니다 .
<Border BorderBrush="Black" BorderThickness="1" CornerRadius="8">
이것에 대한 적절한 대체물입니다. 좀 더 간결합니다
이것이 초기 질문에 대한 답이 아니라는 것을 알고 있지만 방금 만든 둥근 모서리 테두리의 내부 내용을 자르고 싶을 때가 많습니다.
Chris Cavanagh는이를위한 훌륭한 방법 을 제시했습니다.
나는 이것에 대해 몇 가지 다른 접근법을 시도해 보았고 ... 나는 이것이 흔들리는 것이라고 생각합니다.
아래는 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>
이 작업을 직접 수행해야했기 때문에 여기에 다른 답변을 게시 할 것이라고 생각했습니다.
둥근 모서리 테두리를 만들고 내부 내용을 자르는 또 다른 방법이 있습니다 . 이것은 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();
}
}
kobusb의 Border 제어 솔루션의 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
둥근 사각형 테두리에 버튼을 넣으려는 경우 msdn의 예제를 확인해야합니다 . (텍스트 대신) 문제의 이미지를 검색하여 이것을 발견했습니다. 그들의 부피가 큰 외부 직사각형은 (고맙게도) 제거하기 쉽습니다.
ControlTemplate을 변경 했으므로 단추의 동작을 다시 정의해야합니다. 즉, ControlTemplate.Triggers 태그에서 Trigger 태그 (Property = "IsPressed"Value = "true")를 사용하여 클릭 할 때의 버튼 동작을 정의해야합니다. 이것이 내가 잃어버린 시간을 다른 사람에게 구하기를 바랍니다. :)