Can you link the visibility of GroupBox to the visibility of his children?

I have a problem with the breakup of GroupBox. I want the GroupBox to crash if all of its children crashed.

I managed to achieve this using multi-connectivity with properties, as shown below.

<StackPanel>
    <GroupBox>
      <GroupBox.Visibility>
        <MultiBinding 
          Converter="{StaticResource multiBoolOrToVis}"
          ConverterParameter="{x:Static Visibility.Collapsed}"
        >
          <Binding Path="a_visible"/>
          <Binding Path="b_visible"/>
        </MultiBinding>
      </GroupBox.Visibility>
        <GroupBox.Header>
        <Label Content="GroupBox"/>
      </GroupBox.Header>
      <StackPanel>
        <Label 
          Content="A"
          Visibility="{Binding Path=a_visible, Converter={StaticResource boolToVis}}"
        />
        <Label 
          Content="B"
          Visibility="{Binding Path=b_visible, Converter={StaticResource boolToVis}}"
        />
      </StackPanel>
    </GroupBox>
    <Grid>
      <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="*"/>
      </Grid.ColumnDefinitions>
      <CheckBox 
        Content="A Visible"
        Grid.Column="0"
        Grid.Row="1"
        IsChecked="{Binding Path=a_visible, Mode=TwoWay}"
      />
      <CheckBox 
        Content="B Visible"
        Grid.Column="1"
        Grid.Row="1"
        IsChecked="{Binding Path=b_visible, Mode=TwoWay}"
      />
    </Grid>
  </StackPanel>

The problem with this is that we want to be able to do this several times and not worry about giving up the binding. So my question is to do this as a whole, preferably in style. Another requirement is that it must be in xaml and not in the code.

So my ideal answer would be a style, so I could do the following in my xaml.

<StackPanel>
    <GroupBox Style="ChildrenVisibilityStyle">
        <GroupBox.Header>
        <Label Content="GroupBox"/>
      </GroupBox.Header>
      <StackPanel>
        <Label 
          Content="A"
          Visibility="{Binding Path=a_visible, Converter={StaticResource boolToVis}}"
        />
        <Label 
          Content="B"
          Visibility="{Binding Path=b_visible, Converter={StaticResource boolToVis}}"
        />
      </StackPanel>
    </GroupBox>
    <Grid>
      <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="*"/>
      </Grid.ColumnDefinitions>
      <CheckBox 
        Content="A Visible"
        Grid.Column="0"
        Grid.Row="1"
        IsChecked="{Binding Path=a_visible, Mode=TwoWay}"
      />
      <CheckBox 
        Content="B Visible"
        Grid.Column="1"
        Grid.Row="1"
        IsChecked="{Binding Path=b_visible, Mode=TwoWay}"
      />
    </Grid>
  </StackPanel>

, , ; controltemplate, , border visibility.

, . /.

+5
2

MultiDataTrigger, GroupBox,

:

 <StackPanel>
    <GroupBox>
        <GroupBox.Header>
            <Label Content="GroupBox"/>
        </GroupBox.Header>
        <StackPanel>
            <Label x:Name="lbl_a" Content="A" Visibility="{Binding IsChecked, ElementName=chk_a, Converter={StaticResource boolToVis}}"  />
            <Label x:Name="lbl_b" Content="B" Visibility="{Binding IsChecked, ElementName=chk_b, Converter={StaticResource boolToVis}}"  />
        </StackPanel>
        <GroupBox.Style>
            <Style TargetType="GroupBox">
                <Style.Triggers>
                    <MultiDataTrigger>
                        <MultiDataTrigger.Conditions>
                            <Condition Binding="{Binding Visibility, ElementName=lbl_a}" Value="Collapsed" />
                            <Condition Binding="{Binding Visibility, ElementName=lbl_b}" Value="Collapsed" />
                        </MultiDataTrigger.Conditions>
                        <MultiDataTrigger.Setters>
                            <Setter Property="GroupBox.Visibility" Value="Collapsed" />
                        </MultiDataTrigger.Setters>
                    </MultiDataTrigger>
                </Style.Triggers>
            </Style>
        </GroupBox.Style>
    </GroupBox>

    <CheckBox x:Name="chk_a" Content="A Visible" Grid.Column="0" Grid.Row="1" />
    <CheckBox x:Name="chk_b" Content="B Visible" Grid.Column="1" Grid.Row="1"  />

</StackPanel>
+4

, : - GroupBox OnPropertyChanged , GroupBox. , (ren), ( , , ) - FindVisualChildren , , ... :

public sealed class GroupBoxCloseBehavior : DependencyObject
{
    public static readonly DependencyProperty IsEnabledProperty = DependencyProperty.RegisterAttached("IsEnabled", typeof(bool), typeof(GroupBoxCloseBehavior), new PropertyMetadata(false, OnIsEnabledChanged));

    public static bool GetIsEnabled(DependencyObject obj)
    {
        return (bool)obj.GetValue(IsEnabledProperty);
    }

    public static void SetIsEnabled(DependencyObject obj, bool value)
    {
        obj.SetValue(IsEnabledProperty, value);
    }

    private static void OnIsEnabledChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        GroupBox parent = obj as GroupBox;
        if (parent == null)
        {
            return;//Do nothing, or throw an exception depending on your preference
        }

        if (parent.IsLoaded)
        {

            MultiBinding mb = new MultiBinding();
            mb.Converter = new MultiVisibilityToVisibilityConverter();
            if ((bool)e.NewValue)
            {
                foreach (CheckBox child in FindVisualChildren<CheckBox>(parent))
                {
                    mb.Bindings.Add(new Binding("Visibility") { Mode = BindingMode.OneWay, Source = child });
                }
                BindingOperations.SetBinding(parent, UIElement.VisibilityProperty, mb);
            }
            else
            {
                BindingOperations.ClearBinding(parent, UIElement.VisibilityProperty);
            }
        }
        else
        {
            parent.Loaded += (sender, eventArgs) =>
            {
                MultiBinding mb = new MultiBinding();
                mb.Converter = new MultiVisibilityToVisibilityConverter();
                if ((bool)e.NewValue)
                {
                    foreach (CheckBox child in FindVisualChildren<CheckBox>(parent))
                    {
                        mb.Bindings.Add(new Binding("Visibility") { Mode = BindingMode.OneWay, Source = child });
                    }
                    BindingOperations.SetBinding(parent, UIElement.VisibilityProperty, mb);
                }
                else
                {
                    BindingOperations.ClearBinding(parent, UIElement.VisibilityProperty);
                }
            };
        }
    }

    private sealed class MultiVisibilityToVisibilityConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return values.OfType<Visibility>().Any(vis => vis != Visibility.Collapsed) ? Visibility.Visible : Visibility.Collapsed;
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotSupportedException();
        }
    }

    public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
    {
        if (depObj != null)
        {
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
                if (child != null && child is T)
                {
                    yield return (T)child;
                }

                foreach (T childOfChild in FindVisualChildren<T>(child))
                {
                    yield return childOfChild;
                }
            }
        }
    }
}

<StackPanel>
    <GroupBox Header="GroupBox" cl2:GroupBoxCloseBehavior.IsEnabled="True">
        <StackPanel>
            <CheckBox x:Name="CheckOne" Content="CheckBox One"/>
            <CheckBox x:Name="CheckTwo" Content="CheckBox Two"/>
        </StackPanel>
    </GroupBox>
    <StackPanel>
        <Button Content="Hide One" Click="Button_Click_1"/>
        <Button Content="Hide Two" Click="Button_Click_2"/>
    </StackPanel>
</StackPanel>

, , OnPropertyChanged, , GroupBox, , , . . , GroupBox .

0

All Articles