2013-12-12 7 views
6

Привет, я думаю, что это вопросы для начинающих. Я искал все связанные вопросы. Но на все они ответили .xaml. Однако мне нужен обратный код. У меня есть TabControl. Мне нужно установить цвет фона его элементов. Мне нужно установить разные цвета для элементов, когда они выбраны, не выбраны и наведите курсор. Большое вам спасибо за помощь. Я хочу разместить здесь свои коды. Однако в настоящее время все, что у меня есть, это экземпляр TabControl и одно свойство под названием ActiveTabIndex.WPF TabControl, измените цвет фона TabItem на коды C#

--------------------------------------- Редактировать 1 ----- ------------------------------------------

Я добавил событие SelectionChanged

(this.myTabControl as System.Windows.Controls.TabControl) .SelectionChanged + = TabSet_SelectionChanged;

void TabSet_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e) 
     { 
      foreach (System.Windows.Controls.TabItem item in (this.myTabControl as System.Windows.Controls.TabControl).Items) 
      { 
       if (item == (this.myTabControl as System.Windows.Controls.TabControl).SelectedItem) 
       { 
        item.Background = System.Windows.Media.Brushes.Red; 
       } 
       else 
        item.Background = System.Windows.Media.Brushes.Green; 
      } 
     } 

Однако на самом деле я могу установить Зеленый. Цвет фона выбранного элемента сохраняется как цвет по умолчанию, а не красный. Любые намеки на это? Кроме того, я хотел бы знать, как добавить событие для зависания. Не нашли точное событие. Еще раз спасибо.

----------------------- Редактировать 2 ---------------------- ---------

После долгого долгого обсуждения. Я решил (фактически не мое решение) использовать XAML. Да. Я новичок в WPF. Поэтому у меня все еще есть вопросы об этом (мне очень жаль это, пожалуйста, возьми меня). Вопросы здесь: Я хотел бы изменить цвет фона на оранжевый, когда мышь находится над TabItem. Теперь цвет оранжевый, когда мышь находится над ContentPanel и TabItem. Мне нужно, чтобы он был оранжевым, когда мышь находится над TabItem. (Я не уверен, что я достаточно ясен.) Другой вопрос в том, что я хотел бы, чтобы пользователи устанавливали цвет вместо того, чтобы устанавливать его прямо на красный. Думаю, мне нужны привязки. По этому вопросу я буду уверен позже. Просто хочу быть ясным. Большое вам спасибо за всех вас. Действительно полезно.

<TabItem x:Class="MyControls.Tab" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="300"> 
    <TabItem.Style> 
     <Style TargetType="{x:Type TabItem}"> 
      <Setter Property="Template"> 
       <Setter.Value> 
        <ControlTemplate TargetType="{x:Type TabItem}"> 
         <Grid> 
          <Border Name="Border" Margin="0,0,-4,0" BorderThickness="1,1,1,1" CornerRadius="2,12,0,0" > 
           <ContentPresenter x:Name="ContentSite" VerticalAlignment="Center" HorizontalAlignment="Center" ContentSource="Header" Margin="12,2,12,2" RecognizesAccessKey="True"/> 
          </Border> 
         </Grid> 
         <ControlTemplate.Triggers> 

          <Trigger Property="IsSelected" Value="True"> 
           <Setter Property="Panel.ZIndex" Value="100" /> 
           <Setter TargetName="Border" Property="Background" Value="Red" /> 
           <Setter TargetName="Border" Property="BorderThickness" Value="1,1,1,0" /> 
          </Trigger> 

          <Trigger Property="IsSelected" Value="False"> 
           <Setter TargetName="Border" Property="Background" Value="Green" />         
          </Trigger> 
          <Trigger Property="IsMouseOver" Value="True"> 
           <Setter TargetName="Border" Property="Background" Value="Orange" /> 
          </Trigger> 

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

------------- Edit 3 ----------------

Я не достаточно ясно, я думаю. Вот что теперь: Это работает хорошо, если мышь находится над другими вкладками: enter image description here

Но когда мышь находится над кружком области, цвет фона выбранного элемента должен быть красным, а не оранжевый: enter image description here

--------------- Редактировать 4 -------------------

Спасибо за все вы за свой ответ. Теперь, после продолжительной дискуссии с моими пользователями и некоторыми другими, мы хотели бы динамически менять фоновый цвет. Пользователь хочет установить цвет самостоятельно. В принципе, мне нужно сначала сделать привязку (если это термин). Я пробовал следующее. Однако выбранная вкладка не с красным фоном. Я использовал Snoop для проверки, оказалось, что Background задан как красный локально. Я немного запутался здесь. Я спросил, и кто-то дал мне предложение использовать TemplateBinding, поскольку он находится под ControlTemplate. Но я попытался создать свойство зависимостей и что-то в этом роде.Но просто я не понимаю, почему я должен использовать TemplateBinding, так как я прочитал в какой-то статье, что он предназначен для привязки времени компиляции. Я совершенно смущен. Я новичок в WPF, извините, если вопрос является вопросом низкого уровня. Еще раз спасибо!

<TabItem x:Class="MyControl.Tab" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="300"> 
    <TabItem.Style> 
     <Style TargetType="{x:Type TabItem}"> 
      <Setter Property="Template"> 
       <Setter.Value> 
        <ControlTemplate TargetType="{x:Type TabItem}"> 
         <Grid> 
          <Border Name="Border" Margin="0,0,-4,0" BorderThickness="1,1,1,1" CornerRadius="2,12,0,0" > 
           <ContentPresenter x:Name="ContentSite" VerticalAlignment="Center" HorizontalAlignment="Center" ContentSource="Header" Margin="12,2,12,2" RecognizesAccessKey="True"/> 
          </Border> 
         </Grid> 
         <ControlTemplate.Triggers> 
          <Trigger Property="IsSelected" Value="True"> 
           <Setter Property="Panel.ZIndex" Value="100" /> 
           <Setter TargetName="Border" Property="Background" Value="{Binding SelectedBgClr}" /> 
           <Setter Property="Foreground" Value="Yellow" /> 
           <Setter TargetName="Border" Property="BorderThickness" Value="1,1,1,0" /> 
          </Trigger>        
          <Trigger Property="IsSelected" Value="False"> 
           <Setter TargetName="Border" Property="Background" Value="Green" /> 
           <Setter Property="Foreground" Value="AliceBlue"/> 
          </Trigger> 
          <Trigger Property="IsMouseOver" Value="True"> 
           <Setter TargetName="Border" Property="Background" Value="Orange" /> 
           <Setter Property="Foreground" Value="Black"/> 
          </Trigger> 
         </ControlTemplate.Triggers> 
        </ControlTemplate> 
       </Setter.Value> 
      </Setter> 
     </Style> 
    </TabItem.Style> 
</TabItem> 

Код за это:

public Tab() 
     { 
      SelectedBgClr = new SolidColorBrush(Colors.Red); 
      //UnSelectedBgClr = new SolidColorBrush(Colors.Green); 
      //HoverBgClr = new SolidColorBrush(Colors.Orange); 
      InitializeComponent(); 

     } 
public static readonly DependencyProperty SelectedBgClrProperty = DependencyProperty.Register("SelectedBgClr", typeof(Brush), typeof(Tab), new UIPropertyMetadata(null)); 
public Brush SelectedBgClr 
{ 
    get 
    { 
     return (Brush)GetValue(SelectedBgClrProperty); 
    } 
    set 
    { 
     SetValue(SelectedBgClrProperty, value); 
    } 
} 
+2

Очевидно, что на все ответы на ваш вопрос отвечает XAML, потому что ** Это то, что XAML для ** –

+1

HighCore является правильным - выбранный/невыбранный/зависание задается определениями визуального состояния в шаблоне управления. См. Здесь: http://msdn.microsoft.com/en-us/library/ms754137(v=vs.110).aspx – McGarnagle

+0

Спасибо @HighCore !! Понимаю. Однако это проект моего проекта. Нет XAML ... (мне лично тоже не нравится дизайн). Я работаю над этим. Надеюсь получить что-то позже. Во всяком случае, XAML должен быть скомпилирован для кодов. – Payson

ответ

1

WPF позволяет создать новый тип пользовательского управления на основе существующего контроля , вы можете заполнить его объявлением шаблона/стиля на сайте Microsoft и изменить биты в соответствии с вашими потребностями.Создайте новый пользовательский элемент управления под названием MyTabControl и заменить код позади с этим:

public partial class MyTabControl : TabControl 
{ 
    public static readonly DependencyProperty SelectedBgClrProperty = DependencyProperty.Register("SelectedBgClr", 
     typeof(Brush), typeof(MyTabControl), new UIPropertyMetadata(null)); 

    [Category("Appearance")] 
    public Brush SelectedBgClr 
    { 
     get 
     { 
      return (Brush)GetValue(SelectedBgClrProperty); 
     } 
     set 
     { 
      SetValue(SelectedBgClrProperty, value); 
     } 
    } 

    public MyTabControl() 
    { 
     InitializeComponent(); 
    } 
} 

Теперь заменить XAML с этим (вы должны изменить пространство имен к тому, что ваш проект):

<TabControl x:Class="TabDemo.MyTabControl" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     mc:Ignorable="d" 
     Name="tabControl" 
     d:DesignHeight="300" d:DesignWidth="300"> 

<TabControl.Resources> 

    <Style TargetType="{x:Type TabItem}"> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate TargetType="{x:Type TabItem}"> 
        <Grid> 
         <Border Name="Border" Margin="0,0,-4,0" BorderThickness="1,1,1,1" CornerRadius="2,12,0,0" > 
          <ContentPresenter x:Name="ContentSite" VerticalAlignment="Center" HorizontalAlignment="Center" ContentSource="Header" Margin="12,2,12,2" RecognizesAccessKey="True"/> 
         </Border> 
        </Grid> 
        <ControlTemplate.Triggers> 
         <Trigger Property="IsSelected" Value="True"> 
          <Setter Property="Panel.ZIndex" Value="100" /> 
          <Setter TargetName="Border" Property="Background" Value="{Binding ElementName=tabControl, Path=SelectedBgClr}" /> 
          <Setter Property="Foreground" Value="Yellow" /> 
          <Setter TargetName="Border" Property="BorderThickness" Value="1,1,1,0" /> 
         </Trigger> 
         <Trigger Property="IsSelected" Value="False"> 
          <Setter TargetName="Border" Property="Background" Value="Green" /> 
          <Setter Property="Foreground" Value="AliceBlue"/> 
         </Trigger> 
         <Trigger Property="IsMouseOver" Value="True"> 
          <Setter TargetName="Border" Property="Background" Value="Orange" /> 
          <Setter Property="Foreground" Value="Black"/> 
         </Trigger> 
        </ControlTemplate.Triggers> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 
</TabControl.Resources> 

<TabControl.Style> 
    <Style TargetType="{x:Type TabControl}"> 
     <Setter Property="OverridesDefaultStyle" 
      Value="True" /> 
     <Setter Property="SnapsToDevicePixels" 
      Value="True" /> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate TargetType="{x:Type TabControl}"> 
        <Grid KeyboardNavigation.TabNavigation="Local"> 
         <Grid.RowDefinitions> 
          <RowDefinition Height="Auto" /> 
          <RowDefinition Height="*" /> 
         </Grid.RowDefinitions> 
         <VisualStateManager.VisualStateGroups> 
          <VisualStateGroup x:Name="CommonStates"> 
           <VisualState x:Name="Disabled"> 
            <Storyboard> 
             <ColorAnimationUsingKeyFrames Storyboard.TargetName="Border" 
               Storyboard.TargetProperty="(Border.BorderBrush). 
        (SolidColorBrush.Color)"> 
              <EasingColorKeyFrame KeyTime="0" 
             Value="#FFAAAAAA" /> 
             </ColorAnimationUsingKeyFrames> 
            </Storyboard> 
           </VisualState> 
          </VisualStateGroup> 
         </VisualStateManager.VisualStateGroups> 
         <TabPanel x:Name="HeaderPanel" 
        Grid.Row="0" 
        Panel.ZIndex="1" 
        Margin="0,0,4,-1" 
        IsItemsHost="True" 
        KeyboardNavigation.TabIndex="1" /> 
         <Border x:Name="Border" 
        Grid.Row="1" 
        BorderThickness="1" 
        CornerRadius="2" 
        KeyboardNavigation.TabNavigation="Local" 
        KeyboardNavigation.DirectionalNavigation="Contained" 
        KeyboardNavigation.TabIndex="2" Background="{Binding ElementName=tabControl, Path=SelectedBgClr}"> 
          <ContentPresenter x:Name="PART_SelectedContentHost" 
           Margin="4" 
           ContentSource="SelectedContent" /> 
         </Border> 
        </Grid> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 
</TabControl.Style> 

Теперь в вашем MainWindow или как-то просто используйте его, как обычный регулярный TabControl, SelectedBgClr установит как заголовок выбранной вкладки, так и фон основной панели (если вы посмотрите в XAML выше, вы увидите привязки для обоих):

<local:MyTabControl SelectedBgClr="Red"> 
     <TabItem Header="Foo" /> 
     <TabItem Header="Bar" /> 
     <TabItem Header="Baz" /> 
    </local:MyTabControl> 

Обратите внимание, что позади кода минимально, все еще XAML выполняет основную часть работы, а MyTabControl просто используется как оболочка для свойства зависимостей. В реальном приложении вы должны использовать что-то, называемое прикрепленным свойством, так что вам не нужно выводить целый новый класс TabControl.

+0

Спасибо! Отметка! Хорошо, я изменил его, как вы предложили. Однако мой случай здесь немного отличается. Я не собираюсь устанавливать SelectedBgClr = "Red" в любом файле XAML. Вместо этого пользователь установит их с помощью кодов C# (или других способов). Все, что мне нужно, - открыть DependencyProperty для моего пользователя, чтобы позаботиться о цвете фона вкладки. – Payson

+0

Все в порядке, вы можете установить свойства зависимостей в коде, выполнив что-то вроде «myTab.SetValue (MyTabControl.SelectedBgClrProperty, Brushes.Red)». Также можно объявить кисть в блоке и изменить ее свойства во время выполнения, и в этом случае вы ссылаетесь на нее как на DynamicResource, а не на StaticResource. –

4

Причины вы найти его трудно получить ответы на ваш вопрос, потому что вы собираетесь об этом совершенно неправильном пути; Я могу думать о очень немногих случаях, когда изменение контроля в коде, как вы предлагаете, было бы оправдано. WPF был специально разработан, чтобы отделить визуальное состояние от кода, проигнорируйте это на свой страх и риск!

На самом деле ответить на ваш вопрос, хотя следующий будет делать трюк ... вроде ...

foreach (TabItem item in tabControl.Items) 
    item.Background = new SolidColorBrush(Colors.Blue); 

Если вы сделаете это, то вы заметите, что изменяет цвет фона неактивных вкладок, но не текущую выбранную вкладку. Вы также заметите, что выделение вкладки с помощью мыши снова отобразит другой цвет. На самом деле в TabItem есть 7 разных визуальных состояний, добавление кода для каждого из этих случаев начинает становиться беспорядочным и, конечно, намного сложнее, чем использование XAML.

«Правильный» способ управления цветом фона с помощью кода связан с XAML и привязкой данных. Прежде всего перейдите к Microsoft MSDN page for WPF TabControl Styles and Templates, где вы найдете полный шаблон для TabItem. Вставьте это в свой раздел Window.Resources, и теперь вы можете начать играть с тем, как он выглядит (не забудьте также добавить пространства имен и ресурсы). Если вы играете с различными ресурсами, вы заметите, что TabItems используют линейный градиент, ControlLightColor используется для верхней части всех вкладок, ControlMediumColor используется для нижней части невыбранных вкладок, а ControlDarkColor используется для нижней части текущей выбранной вкладки , Чтобы контролировать это во время выполнения, вам нужно найти все экземпляры этих ресурсов, разбросанные по стилю, и привязать их к свойству в вашем коде, а затем написать ValueConverter, который преобразует все ваше свойство (я предполагаю логическое) в щетка. Другой (лучший) метод, и тот, который не требует какого-либо дополнительного кода, который должен быть написан вообще, будет заключаться в использовании DataTrigger, который изменяет визуальное появление TabItem в ответ на ваше значение изменения свойства, но это немного мимо «начинающего» этапа, и вам нужно будет предоставить дополнительную информацию о вашем конкретном случае.

UPDATE: Это, кажется, работает для меня:

void TabSet_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e) 
    { 
     foreach (TabItem item in tabControl.Items) 
      item.Background = new SolidColorBrush(item.IsSelected ? Colors.Green : Colors.Red); 
    } 

Я до сих пор говорят, что это ужасно неправильно, хотя. Если вы абсолютно настаиваете на том, чтобы делать это в коде, вам не следует использовать WPF. Это совершенно неправильная технология, я не могу это подчеркнуть достаточно сильно!

UPDATE # 2: Вы почти там, вы просто должны сделать это в окне, на котором размещен элемент управления вкладки:

<Window x:Class="MyWpfApplication.Window1" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="Window1" Height="300" Width="300" WindowState="Maximized"> 

    <Window.Resources> 

     <Style TargetType="{x:Type TabItem}"> 
      <Setter Property="Template"> 
       <Setter.Value> 
        <ControlTemplate TargetType="{x:Type TabItem}"> 
         <Grid> 
          <Border Name="Border" Margin="0,0,-4,0" BorderThickness="1,1,1,1" CornerRadius="2,12,0,0" > 
           <ContentPresenter x:Name="ContentSite" VerticalAlignment="Center" HorizontalAlignment="Center" ContentSource="Header" Margin="12,2,12,2" RecognizesAccessKey="True"/> 
          </Border> 
         </Grid> 
         <ControlTemplate.Triggers> 

          <Trigger Property="IsSelected" Value="True"> 
           <Setter Property="Panel.ZIndex" Value="100" /> 
           <Setter TargetName="Border" Property="Background" Value="Red" /> 
           <Setter TargetName="Border" Property="BorderThickness" Value="1,1,1,0" /> 
          </Trigger> 

          <Trigger Property="IsSelected" Value="False"> 
           <Setter TargetName="Border" Property="Background" Value="Green" /> 
          </Trigger> 
          <Trigger Property="IsMouseOver" Value="True"> 
           <Setter TargetName="Border" Property="Background" Value="Orange" /> 
          </Trigger> 

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

    </Window.Resources> 

    <TabControl> 
     <TabItem Header="Foo" /> 
     <TabItem Header="Bar" /> 
     <TabItem Header="Baz" /> 
    </TabControl> 

</Window> 
+0

Большое спасибо @ Марку Фельдману. Сейчас я работаю над этим. Теперь я сделал следующее: – Payson

+0

Я добавил событие SelectionChanged; и я установил цвет фона там. Пожалуйста, см. Мое редактирование, поскольку здесь недостаточно места. – Payson

+0

Код обновлен, см. Мой ответ. –

Смежные вопросы