Autor Beitrag
sworddancer
Hält's aus hier
Beiträge: 15



BeitragVerfasst: Mi 22.04.09 16:44 
Hallo zusammen,

Ich habe derzeit ein Problem mit dem erstellen eines speziellen TabControls und hoffe ihr könnt mir helfen. Die sache ist, ich brauche eine Tabcontrol welches im anstelle von den normalen Tabs, im nicht selectierten Zustand, einen Button anzeigt. Wenn der Button einen bestimmten zustand erreicht, zurzeit nach einem Doppelklick, soll das item erst selektiert werden. Für die Darstellung habe ich einen Style defeniert der auch das richtige darstellt.
ausblenden volle Höhe XML-Daten
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
<SolidColorBrush x:Key="TabControlNormalBorderBrush" Color="#8C8E94"/>
  <LinearGradientBrush x:Key="ButtonNormalBackground" EndPoint="0,1" StartPoint="0,0">
    <GradientStop Color="#F3F3F3" Offset="0"/>
  <GradientStop Color="#EBEBEB" Offset="0.5"/>
  <GradientStop Color="#DDDDDD" Offset="0.5"/>
  <GradientStop Color="#CDCDCD" Offset="1"/>
  </LinearGradientBrush>
  <LinearGradientBrush x:Key="TabItemHotBackground" EndPoint="0,1" StartPoint="0,0">
    <GradientStop Color="#EAF6FD" Offset="0.15"/>
    <GradientStop Color="#D9F0FC" Offset=".5"/>
    <GradientStop Color="#BEE6FD" Offset=".5"/>
    <GradientStop Color="#A7D9F5" Offset="1"/>
  </LinearGradientBrush>
  <SolidColorBrush x:Key="TabItemSelectedBackground" Color="#F9F9F9"/>
    <SolidColorBrush x:Key="TabItemHotBorderBrush" Color="#3C7FB1"/>
    <SolidColorBrush x:Key="TabItemDisabledBackground" Color="#F4F4F4"/>
    <SolidColorBrush x:Key="TabItemDisabledBorderBrush" Color="#FFC9C7BA"/>

<Style x:Key="TabItemStyle" TargetType="{x:Type TabItem}">
  <Setter Property="FocusVisualStyle" Value="{StaticResource TabItemFocusVisual}"/>
  <Setter Property="Foreground" Value="Black"/>
  <Setter Property="Padding" Value="6,1,6,1"/>
  <Setter Property="BorderBrush" Value="{StaticResource TabControlNormalBorderBrush}"/>
  <Setter Property="Background" Value="{StaticResource ButtonNormalBackground}"/>
  <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
  <Setter Property="VerticalContentAlignment" Value="Stretch"/>
  <Setter Property="Template">
    <Setter.Value>
  <ControlTemplate TargetType="{x:Type TabItem}">
    <DockPanel SnapsToDevicePixels="true" Margin="-30,0,0,0"   x:Name="grid" Height="177.5" LastChildFill="False" Width="150">
            <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="0,0,0,0" Padding="{TemplateBinding Padding}" Width="113" Height="71" DockPanel.Dock="Bottom">
        <Canvas Width="175.5" Height="200" Margin="-33,-91,0,0">
    <StateButton Width="104" Height="48" Canvas.Top="99" Canvas.Left="31.5" x:Name="safeActivationButton" CurrentState="NotActivated" >
                  <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" x:Name="Content" ContentSource="Header" RecognizesAccessKey="True" />
    </StateButton>
          </Canvas>
      </Border>
    </DockPanel>
  <ControlTemplate.Triggers>
    <Trigger Property="StateButton.State" Value="Activated" SourceName="safeActivationButton">         
            <Setter Property="IsSelected" Value="true" />
    </Trigger>
    <Trigger Property="IsSelected" Value="true">
      <Setter Property="Panel.ZIndex" Value="1"/>
      <Setter Property="Background" TargetName="Bd" Value="{DynamicResource TabItemSelectedBackground}"/>
      <Setter Property="BorderThickness" TargetName="Bd" Value="1,1,1,0"/>
      <Setter Property="CornerRadius" TargetName="Bd" Value="5,5,0,0"/>
      <Setter Property="Margin" TargetName="Bd" Value="0,0,0,-2"/>
      <Setter Property="HorizontalAlignment" TargetName="Content" Value="Center"/>
      <Setter Property="VerticalAlignment" TargetName="Content" Value="Center"/>
      <Setter Property="Background" TargetName="safeActivationButton" Value="{x:Null}"/>
      <Setter Property="BorderBrush" TargetName="safeActivationButton" Value="{x:Null}"/>
      <Setter Property="IsEnabled" TargetName="safeActivationButton" Value="False"/>
      <Setter Property="Foreground" TargetName="safeActivationButton" Value="#FF090909"/>
    </Trigger>
  </ControlTemplate.Triggers>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>


Mit dieser Konfiguration funktioniert das durch wescheln allerdings nur einmal. Ich verumte das der Fehler an dem folgenden Trigger liegt:

ausblenden XML-Daten
1:
2:
3:
<Trigger Property="StateButton.State" Value="Activated" SourceName="safeActivationButton">         
  <Setter Property="IsSelected" Value="true" />
</Trigger>


Ich denke das nachdem eine anderer Button diesen State erreicht hat wird beim dem vorher aktivierten Button der IsSelected auf False gesetzt und das Bindng wird dadurch unterbrochen.

Meine überlegung war nun das ich ein eigenes control schreibe welches von TabItem ableitet. Diese soll sich auf das click Event des State Buttons regestriern und das property is selected selbst setzen. Leider komme ich nicht an den Button drann, da dieser über ein Style zugewiesen wurde. Habe schon versucht mit hilfe von FindElement daran zu kommen und folgende Methode hat leider auch nicht funktioniert:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
public static childItem FindVisualChild<childItem>(DependencyObject obj) where childItem : DependencyObject
        {
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(obj, i);
                if (child != null && child is childItem)
                {
                    return (childItem) child;
                }
                else
                {
                    var childOfChild = FindVisualChild<childItem>(child);
                    if (childOfChild != null)
                    {
                        return childOfChild;
                    }
                }
            }
            return null;
        }


Hätte einer von euch vielleicht noch eine Lösung wie ich an den Button komme?
Habt ihr vielleicht eine andere idee wie man dieses Problem lösen könnte?
Habe auch versucht dem Button das Click ereigniss direkt im XAML zu übergeben aber das problem ist
das die Methode in dem UserControl wo das TabControl verwendet wird stehen muss wobei das, das TabControl ja selbst regelen soll.

Vielen dank für Eure Hilfe schonmal im vorraus.
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Mi 22.04.09 18:10 
user profile iconsworddancer hat folgendes geschrieben Zum zitierten Posting springen:
Ich denke das nachdem eine anderer Button diesen State erreicht hat wird beim dem vorher aktivierten Button der IsSelected auf False gesetzt und das Bindng wird dadurch unterbrochen.
Genau, nur ist es ja eben kein Binding ;) . Da der Button aber beim Wechseln wohl wieder in den Deactivated-Zustand zurückkehren soll, ist hier ein Two Way Binding aber auch viel passender als ein Trigger. Nur einen Value Converter brauchst du dazu noch.

_________________
>λ=
sworddancer Threadstarter
Hält's aus hier
Beiträge: 15



BeitragVerfasst: Do 23.04.09 08:37 
Morgen Kha,
danke für deine schnelle Antwort. Habe es auch gerade eben probiert. Allerdings leider ohne erfolg. Habe es einmal so probiert
ausblenden XML-Daten
1:
<Setter Property="IsSelected" Value="{Binding Path = State, ElementName = safeActivationButton, Mode = TwoWay, Converter = {StaticResource StateConverter}}" />					


und einmal so

ausblenden XML-Daten
1:
<StateButton Width="104" Height="48" Canvas.Top="99" Canvas.Left="31.5" x:Name="safeActivationButton" State="{Binding Path = IsSelected, Converter = {StaticResourc StateConverter, Mode = TwoWay}}" Click="safeActivationButton_Click" >					


Mein Converter ist folgender masen implementiert

ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
  public class BoolStateConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            string state = value as string;

            if (state != null)
            {
                SafeActivationButton.ButtonState currentState =
                    (SafeActivationButton.ButtonState) Enum.Parse(typeof (SafeActivationButton.ButtonState), state);

                switch (currentState)
                {
                    case SafeActivationButton.ButtonState.NotActivated:
                        return false;
                    case SafeActivationButton.ButtonState.ConfirmActivated:
                        return false;
                    case SafeActivationButton.ButtonState.Activated:
                        return true;
                    case SafeActivationButton.ButtonState.ConfirmNotActivated:
                        return true;
                    default:
                        throw new ArgumentOutOfRangeException();
                }
            }
            return false;
        }
   

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            string state = value as string;

            if (state != null)
            {
                bool isSelected = bool.Parse(state);

                if (isSelected)
                {
                    return SafeActivationButton.ButtonState.Activated;
                }
                
                return SafeActivationButton.ButtonState.NotActivated;
            }

            return SafeActivationButton.ButtonState.NotActivated;
        }
    }


für den Anderen weg habe ich die Klasse natürlich angepasst. Das Problem ist das der Converter gar nicht aufgerufen wird. Ich kann weder rein debuggen noch sonst was. Irgendwie wird das Binding nicht aktiv. Habe hier noch den Code wie ich mein dependecy Property des Button erstelle eingefügt

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
 public static readonly DependencyProperty StateProperty = DependencyProperty.Register(
            "State"
            typeof(ButtonState),
            typeof (SafeActivationButton),
            new PropertyMetadata(ButtonState.NotActivated));

        /// <summary>
        /// Set the state of the button. (This function is needed for the WPF integration)
        /// </summary>
        /// <param name="d">the dependency object</param>
        /// <param name="value">the new state of the button</param>
        public static void SetState(DependencyObject d, ButtonState value)
        {
            d.SetValue(StateProperty, value);
        }

        /// <summary>
        /// Get the current diameter for the circle. (This function is needed for the WPF integration)
        /// </summary>
        /// <param name="d">the dependency object</param>
        /// <returns>the current diameter of the circle</returns>
        public static double GetDiameter(DependencyObject d)
        {
            return (double)d.GetValue(DiameterProperty);
        }


Hast du, oder jemand anderst, vielleicht eine Ahnung woran das liegen kann?
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Do 23.04.09 11:35 
user profile iconsworddancer hat folgendes geschrieben Zum zitierten Posting springen:
Das Problem ist das der Converter gar nicht aufgerufen wird. Ich kann weder rein debuggen noch sonst was.
Zeigt das Output-Fenster irgendwelche Binding-Fehler an? Beim zweiten Xaml sind ja ein paar Schreibfehler drin.

_________________
>λ=