2011-06-23 9 views
5

Próbuję utworzyć coś podobnego do poniższego obrazu w WPF. Ta kontrola ma być podstawowym widokiem wszystkiego w mojej aplikacji i będzie znajdować się wewnątrz kontrolki okna z tłem (prawdopodobnie pewnego rodzaju gradientem).Element narożny WPF Cut

Wymagania są następujące:

  • Zaokrąglone narożniki z trzech stron (lewy górny róg, prawy dolny lewy i dolny)
  • Odciąć zakładki patrząc róg na górze po prawej stronie, który ma tło za " wycięty obszar "przezroczysty", więc gradient tła z okna pokazuje (sprawiając, że wygląda na to, że został obcięty)
  • Obszar tytułu powinien być kontenerem zawartości, aby umieścić w nim dowolne elementy, takie jak ikony i tekst.
  • Obszar zawartości musi mieć minimum wysokość, a następnie rośnie, jeśli zawartość wewnętrzna przekracza (nie w locie - po prostu wysokość wszystkich elementów w nim zawartych)

Walczyłem z tym od wielu godzin, ale będąc nowym w WPF, Zaczynam się biec w kółko. Sądzę, że korzyści płynące z elastyczności WPF są ogromne, ale dla osób dopiero zaczynających jest to zbyt zniechęcające.

Każda pomoc będzie bardzo ceniona! Dzięki!

Content Layout

Odpowiedz

4

Tabby

Nie wiem, jak "wypełnić" klip, więc zrobiłem klip w kodzie. Daj mi znać, jeśli potrzebujesz więcej pomocy dodając więcej właściwości do kontrolowania kolorów itd tu idzie:

Kod:

public class Tabby : HeaderedContentControl 
{ 
    static Tabby() 
    { 
     DefaultStyleKeyProperty.OverrideMetadata(typeof(Tabby), new FrameworkPropertyMetadata(typeof(Tabby))); 
    } 

    public double DogEar 
    { 
     get { return (double)GetValue(DogEarProperty); } 
     set { SetValue(DogEarProperty, value); } 
    } 

    public static readonly DependencyProperty DogEarProperty = 
     DependencyProperty.Register("DogEar", 
     typeof(double), 
     typeof(Tabby), 
     new UIPropertyMetadata(8.0, DogEarPropertyChanged)); 

    private static void DogEarPropertyChanged(
     DependencyObject obj, 
     DependencyPropertyChangedEventArgs e) 
    { 
     ((Tabby)obj).InvalidateVisual(); 
    } 

    public Tabby() 
    { 
     this.SizeChanged += new SizeChangedEventHandler(Tabby_SizeChanged); 
    } 

    void Tabby_SizeChanged(object sender, SizeChangedEventArgs e) 
    { 
     var clip = new PathGeometry(); 
     clip.Figures = new PathFigureCollection(); 
     clip.Figures.Add(
      new PathFigure(
       new Point(0, 0), 
       new[] { 
        new LineSegment(new Point(this.ActualWidth - DogEar, 0), true), 
        new LineSegment(new Point(this.ActualWidth, DogEar), true), 
        new LineSegment(new Point(this.ActualWidth, this.ActualHeight), true), 
        new LineSegment(new Point(0, this.ActualHeight), true) }, 
       true) 
     ); 
     this.Clip = clip; 
    } 
} 

Generic.xaml

<Style TargetType="{x:Type local:Tabby}"> 
    <Setter Property="Padding" 
      Value="5" /> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type local:Tabby}"> 
       <Grid> 
        <Grid.RowDefinitions> 
         <RowDefinition Height="auto" /> 
         <RowDefinition Height="auto" /> 
        </Grid.RowDefinitions> 
        <Border CornerRadius="3,0,0,0" 
          BorderBrush="Black" 
          BorderThickness="1" 
          Background="Black"> 
         <ContentPresenter Content="{TemplateBinding Header}" 
              Margin="{TemplateBinding Padding}" /> 
        </Border> 
        <Border CornerRadius="0,0,3,3" 
          BorderBrush="Black" 
          BorderThickness="1" 
          Background="White" 
          Grid.Row="1"> 

         <ContentPresenter Content="{TemplateBinding Content}" 
              Margin="{TemplateBinding Padding}" /> 
        </Border> 
       </Grid> 

      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

Używanie go:

<my:Tabby DogEar="12" 
      x:Name="tabby1"> 
    <my:Tabby.Header> 
     <TextBlock Foreground="White">Header</TextBlock> 
    </my:Tabby.Header> 
    <my:Tabby.Content> 
     <TextBlock Text="Content can be anything" /> 
    </my:Tabby.Content> 
</my:Tabby> 
+0

Perfect !! To jest martwe, czego potrzebowałem. Teraz jedyne pytanie, które zawsze mam w WPF ... jak w świecie nauczyłeś się wymyślać to, co zrobiłeś? Zasoby naprawdę uczące się WPF w użytecznych modach, takich jak ta, wydają się tak niewiarygodnie rzadkie. – RubyHaus

+0

Pięć lat temu zrobiłem trudną część, w której teraz jesteś. Czytałem książki, kodowałem wiele projektów, popełniałem błędy i pytałem innych (nie było ich wtedy zbyt wiele, ale miałem szczęście mieć dostęp do niektórych osób pracujących nad WPF). I nawet teraz wciąż się uczę. Poczekaj, dotrzesz tam. –

4

Spróbuj zacząć:

<Grid Width="100" Height="100"> 
    <Border Background="Green" CornerRadius="8,0,8,8"> 
     <Border.Clip> 
     <PathGeometry> 
      <PathGeometry.Figures> 
      <PathFigure StartPoint="0,0"> 
       <PathFigure.Segments> 
       <LineSegment Point="90,0"/> 
       <LineSegment Point="100,10"/> 
       <LineSegment Point="100,100"/> 
       <LineSegment Point="0,100"/> 
       </PathFigure.Segments> 
      </PathFigure> 
      </PathGeometry.Figures> 
     </PathGeometry> 
     </Border.Clip> 
    </Border> 
    </Grid> 
+0

Myślę, że będzie idealnie! Dzięki!! – RubyHaus

+0

Twoja metoda działała całkiem nieźle, ale poniższa odpowiedź (kontrola "Tabby") okazała się dla mnie lepsza, ponieważ potrzebowałem czegoś, co można łatwo ponownie wykorzystać. Zostawiłem jednak dla ciebie głosowanie w górę. Dzięki jeszcze raz! – RubyHaus

+0

Tak też zacząłem, ale wkrótce utknąłem, gdy nie znałem rozmiaru kontrolki i musiałem wywnioskować rozmiar Klipu. –

0

Oto kod I umieścić razem przy użyciu niestandardowego formantu.

Kod kontrolny:

using System; 
using System.Windows; 
using System.Windows.Controls; 

namespace Test 
{ 
    public class ContentCard : HeaderedContentControl 
    { 
     static ContentCard() 
     { 
      DefaultStyleKeyProperty.OverrideMetadata(typeof(ContentCard), new FrameworkPropertyMetadata(typeof(ContentCard))); 
     } 
    } 
} 

Kontrola XAML (w Themes folderu/Generic.xaml)

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        xmlns:test="clr-namespace:Test"> 
    <Style TargetType="{x:Type test:ContentCard}"> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate TargetType="{x:Type test:ContentCard}"> 
        <Grid Background="Transparent"> 
         <Grid.RowDefinitions> 
          <RowDefinition Height="30" /> 
          <RowDefinition Height="*" /> 
         </Grid.RowDefinitions> 
         <Grid.ColumnDefinitions> 
          <ColumnDefinition Width="*" /> 
          <ColumnDefinition Width="20" /> 
         </Grid.ColumnDefinitions> 

         <Border Grid.Row="0" Grid.Column="0" Background="{TemplateBinding Background}" CornerRadius="10,0,0,0" Height="30"> 
          <ContentControl Content="{TemplateBinding Header}" VerticalAlignment="Center" Margin="10,0,0,0" /> 
         </Border> 
         <Path Grid.Row="0" Grid.Column="1" Fill="{TemplateBinding Background}" Data="M0,0 L20,15 L20,30 L0,30 L0,0Z"/> 
         <Border Grid.Row="1" Grid.ColumnSpan="2" BorderBrush="{TemplateBinding Background}" BorderThickness="1,0,1,1" CornerRadius="0,0,10,10" Padding="5" Background="White"> 
          <ContentControl Content="{TemplateBinding Content}" /> 
         </Border> 
        </Grid> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 
</ResourceDictionary> 

To jak go używać:

<test:ContentCard Grid.RowSpan="4" Grid.ColumnSpan="2" Margin="200" Background="Black"> 
    <test:ContentCard.Header> 
     <TextBlock Text="Title" Foreground="White" /> 
    </test:ContentCard.Header> 
    <test:ContentCard.Content> 
     <TextBlock Text="This is some content" Foreground="Black" /> 
    </test:ContentCard.Content> 
</test:ContentCard> 
Powiązane problemy