2013-04-09 9 views
5

Bir GroupBox'un çökmesi için bir sorunla karşılaşıyorum. Tüm çocuklar çökerse çökecek bir GroupBox istiyorum.GroupBox'un görünürlüğünü, çocukların görünürlüğüne bağlayabilir misiniz?

Bunu, aşağıda gösterildiği gibi, özelliklerle çoklu bağlantı kullanarak başarmayı başardım.

<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> 

bu sorun bu birden çok kez yapmak ve bağlayıcı bir kapalı bırakarak dert etmek isterler olduğunu. Yani benim sorum bu genel olarak, tercihen bir tarzda bunu yapmanın bir yolu var. Başka bir gereksinim, arkasında xaml kodu olmamalıdır.

Bu yüzden ideal cevabım bir stil olurdu, böylece xaml'ımda aşağıdakileri yapabilirdim.

<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> 

Bu sorulara baktım ve bunun mümkün olmadığını düşünmeme neden oluyorlar; binding in controltemplate, stackpanel visibility, border visibility.

Bu daha önce yanıtlanmış olsaydı özür dilerim. Herhangi bir cevap/yorum için şimdiden teşekkür ederiz.

<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> 

cevap

4

Sen GroupBox daraltmak için bir MultiDataTrigger kullanabilirsiniz ilk etmektir Üst grubun üstündeki GroupBox'a ve OnPropertyChanged geridöngü döngüsüne tüm çocuklar üzerinde bir ekleme ve daha sonra GroupBox Visibility özelliğine bağlanan bir çokboyutlu bağlama ekleme. Bu yaklaşımdaki problem, çok-öyküye dahil etmek istediğiniz çocuğun (ren) tipini (türlerini) belirtmeniz gerekmesidir (çünkü onları ebeveynin durumunu dikte eden gruba eklemek için bulmanız gerekir) - her şeyi yakalamak istiyorsanız FindVisualChildren istediğiniz birden jenerik türleri ile çağrılacak gerekecektir o ... kolayca olsa yapılması için:

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> 

bu başka bir yol yaparak, alt öğeler üzerinde iliştirilmiş bir özellik koyarak OnPropertyChanged bir ana GroupBox'u aramak için ağaca doğru yürürken daha iyi olabilir, ancak kaç tane elementin olduğunu bilmeme zahmetine sahip olursunuz. Bu sadece bağlayıcı bir sınırlamadır. En azından GroupBox ekli özelliği ile ihtiyacınız olan bağlamayı yapılandırabilirsiniz.

+0

Ancak başka bir GroupBox yapmak veya başka bir öğe eklemek istersek, her seferinde koşulları eklemem gerekmeyecek mi? Bu MultiBinding ile aynı sorun olurdu – davidcorne

0

ekli davranışları ile hem iki yaklaşım vardır: Çocuk İşte

çalışan bir örnektir çökmüş zaman