Как я могу придать элементу WPF прямоугольную плоскую 3D-рамку?

StackOverflow https://stackoverflow.com/questions/581838

  •  06-09-2019
  •  | 
  •  

Вопрос

Я хотел бы создать прямоугольный "плоский 3D" вид для одного из моих шаблонов управления.В самой простой версии это означает наличие линии внизу, которая темнее, чем вверху, и, возможно, также некоторые различия между левой и правой линиями.

Более сложная версия позволила бы мне предоставить одну или несколько кистей, чтобы можно было наносить градиенты.

Значение по умолчанию <Border> элемент в WPF позволяет указать разную толщину для каждого края, но я не могу найти способ указать несколько кистей.

Итак, как я могу добиться желаемого эффекта как можно проще?

Редактировать было предложено, чтобы я опубликовал пример того, как я хочу это использовать.Лично я был бы рад иметь стиль или пользовательский элемент управления.Пользовательский элемент управления может быть использован таким образом:

<FourSidedBorder LeftSideBrush="#00f" RightSideBrush="#0f0" ... />

Или, возможно, еще проще:

<FourSidedBorder BorderBrush="#00f,#0f0,#f00,#fff"
                 BorderThickness="1,2,3,4" ... />

Это всего лишь идеи.Любое разумное, краткое решение приветствуется.

Это было полезно?

Решение 2

Вот решение, которое я разработал, которое позволяет достичь большей части того, чего я хочу.Это не дает полного контроля над всеми четырьмя сторонами независимо, но это дает прямоугольный плоский 3D-вид, который я хочу.

Вот как это выглядит:

Вставьте это в Каксамл чтобы увидеть это своими глазами:

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Background="#CCC">
  <Page.Resources>
    <!-- A brush for flat 3D panel borders -->
    <LinearGradientBrush x:Key="Flat3DBorderBrush"
                         StartPoint="0.499,0" EndPoint="0.501,1">
      <GradientStop Color="#FFF" Offset="0" />
      <GradientStop Color="#DDD" Offset="0.01" />
      <GradientStop Color="#AAA" Offset="0.99" />
      <GradientStop Color="#888" Offset="1" />
    </LinearGradientBrush>
  </Page.Resources>
  <Grid>  
    <!-- A flat 3D panel -->
    <Border
          HorizontalAlignment="Center" VerticalAlignment="Center"
          BorderBrush="{StaticResource Flat3DBorderBrush}"
          BorderThickness="1" Background="#BBB">

          <!-- some content here -->
          <Control Width="100" Height="100"/>

    </Border>  
  </Grid>
</Page>

Надеюсь, это поможет кому-то еще.Я все еще нахожусь в поиске инновационных решений этой проблемы, поэтому продолжайте публиковать, и я приму лучший ответ, чем этот.

Другие советы

Я сделал что-то подобное, просто поместив несколько границ непосредственно друг на друга.Например.:

<Border 
  x:Name="TopAndLeft" 
  BorderThickness="3,3,0,0" 
  BorderBrush="{x:Static SystemColors.ControlLightBrush}">
<Border 
  x:Name="BottomAndRight" 
  BorderThickness="0,0,3,3" 
  BorderBrush="{x:Static SystemColors.ControlDarkBrush}">
    <ContentPresenter ... />
</Border>
</Border>

Это обеспечивает дополнительное преимущество всех других функций, которые предоставляет border - угловой радиус и тому подобное.

Честно говоря, вероятно, самым простым способом было бы использовать методы наслоения.Например, создайте сетку, подобную этой:

  <Grid Width="50" Height="50">  
     <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
        <RowDefinition Height="Auto" />
     </Grid.RowDefinitions>
     <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="Auto" />
     </Grid.ColumnDefinitions>

     <!-- Top Border -->
     <Border Height="3" Background="LightGray" Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2" />

     <!-- Right Border -->
     <Border Width="3" Background="DarkGray" Grid.Column="2" Grid.Row="0" Grid.RowSpan="3" />

     <!-- Content -->
     <Border Background="Gray" Grid.Row="1" Grid.Column="1" />

     <!-- Left Border -->
     <Border Width="3" Background="LightGray" Grid.Row="1" Grid.Column="0" Grid.RowSpan="2" />

     <!-- Bottom Border -->
     <Border Height="3" Background="DarkGray" Grid.Row="2" Grid.Column="1" />

  </Grid>

Я думаю, вы уловили идею.Это, вероятно, самый простой способ сделать это.Вы могли бы настроить это как шаблон и использовать его следующим образом:

<Template x:Key="My3DBorder" TargetType="ContentControl">
    <!-- Put the Grid definition in here from above -->
</Template>

<ContentControl Template="{StaticResource My3dBorder}">
   <!-- My Content Goes Here -->
</ContentControl>

вы можете сослаться на Структура презентации.Классический сборка, а затем использование

<Window xmlns:mwt="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Classic">
...

<Grid Width="50" Height="50">
    <mwt:ClassicBorderDecorator BorderThickness="3,3,3,3"/>
</Grid>

Я использовал этот метод для просмотра шаблонов элементов управления чтобы увидеть, как были оформлены кнопки по умолчанию

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top