【发布时间】:2011-05-25 20:11:48
【问题描述】:
有 4 个扩展器控件。当一个扩展器展开时,如何让所有其他扩展器折叠/关闭?
【问题讨论】:
有 4 个扩展器控件。当一个扩展器展开时,如何让所有其他扩展器折叠/关闭?
【问题讨论】:
试试下面的代码:
<StackPanel Name="StackPanel1">
<StackPanel.Resources>
<local:ExpanderToBooleanConverter x:Key="ExpanderToBooleanConverter" />
</StackPanel.Resources>
<Expander Header="Expander 1"
IsExpanded="{Binding SelectedExpander, Mode=TwoWay, Converter={StaticResource ExpanderToBooleanConverter}, ConverterParameter=1}">
<TextBlock>Expander 1</TextBlock>
</Expander>
<Expander Header="Expander 2"
IsExpanded="{Binding SelectedExpander, Mode=TwoWay, Converter={StaticResource ExpanderToBooleanConverter}, ConverterParameter=2}">
<TextBlock>Expander 2</TextBlock>
</Expander>
<Expander Header="Expander 3"
IsExpanded="{Binding SelectedExpander, Mode=TwoWay, Converter={StaticResource ExpanderToBooleanConverter}, ConverterParameter=3}">
<TextBlock>Expander 3</TextBlock>
</Expander>
<Expander Header="Expander 4"
IsExpanded="{Binding SelectedExpander, Mode=TwoWay, Converter={StaticResource ExpanderToBooleanConverter}, ConverterParameter=4}">
<TextBlock>Expander 4</TextBlock>
</Expander>
</StackPanel>
public class ExpanderToBooleanConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return (value == parameter);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (System.Convert.ToBoolean(value)) return parameter;
return null;
}
}
public class ExpanderListViewModel
{
public Object SelectedExpander { get; set; }
}
StackPanel1.DataContext = new ExpanderListViewModel();
在 XAML 中,我们有 4 个扩展器。它们都从容器StackPanel 到DataContext 继承了ViewModel(ExpanderListViewModel 类型)。
它们都绑定到 ViewModel 类的单个属性。并在绑定中使用ConverterParameter 为自己定义了一个唯一索引。每当您展开扩展器时,该索引都会保存在 SelectedExpander 属性中。使用该索引,如果存储索引与给定索引匹配,Converter 返回true,如果存储索引不匹配,则返回false。
在Converter 类的Convert 和ConvertBack 方法中放置一个断点,你会看到发生了什么。
【讨论】:
Silverlight Toolkit,它正式属于future Silverlight。它由来自Microsoft 的人员维护,添加到其中的控件将添加到Silverlight 的未来版本中。所以,你没有理由不使用它。
ConverterParameter 时,我仍然可以工作(一次只打开一个扩展器)。但是,当我扩展一个时,难道不应该扩展所有这些吗?在转换器的Convert 方法中设置断点后,似乎value == parameter 的表达式始终为假,即使保持相同的值......对此有何解释?
==运算符比较对象时,它实际上比较的是引用而不是对象的内容。因此,为了使代码按预期工作,您应该在比较之前将value 和parameter 转换为整数。因此,Convert 方法的 return 语句应该是 return (System.Convert.ToInt32(value) == System.Convert.ToInt32(parameter));
我就是这样做的:
1) 添加了一个 StackPanel 并且必须添加一个名称标签属性(因为这是主节点)。
StackPanel Name="StackPanel1"
2) 根据需要添加任意数量的扩展器(如果需要,可以添加 1 到 100 个),每个扩展器必须具有:-
Expanded="Expander_Expanded"
添加(注意所有的措辞都 100% 相同)。
3) 没有其他细节需要匹配每个(不需要高度的名称等)。
Xaml:
<StackPanel Name="StackPanel1">
<Expander Header="Expander 1" Expanded="Expander_Expanded">
<TextBlock>Expander 1</TextBlock>
</Expander>
<Expander Header="Expander 2" Expanded="Expander_Expanded">
<TextBlock>Expander 2</TextBlock>
</Expander>
<Expander Header="Expander 3" Expanded="Expander_Expanded" >
<TextBlock>Expander 3</TextBlock>
</Expander>
<Expander Header="Expander 4" Expanded="Expander_Expanded" >
<TextBlock>Expander 4</TextBlock>
</Expander>
4) 要控制名为“StackPanel1”StackPanel 上所有“Expanders”的打开/关闭,您只需添加以下代码一次。
VB 代码隐藏:
Private Sub Expander_Expanded(sender As Object, e As RoutedEventArgs)
For Each exp As Expander In StackPanel1.Children
If exp IsNot sender Then
exp.IsExpanded = False
End If
Next
End Sub
5)现在您可以更改/添加什么内容、按钮、文本框等。您只需要不更改 2 件事 1、“StackPanel 名称”2、“Expander Expanded”而不更新代码隐藏,否则不会工作。
希望这些信息对您有所帮助。
发生了什么事?
1) 所有面板都是父面板,该面板上的所有控件都是子面板,
2) 所有控件都是父面板的子控件。
3) 一个类一次处理一个调用。
4) 类处理孩子。
6) 班级移动到下一个孩子。
7) 询问完所有孩子后停止。
所以伪代码是这样的:
1) 听一个孩子的名字 x
2) 询问父母孩子列表中的每个孩子
3) 如果孩子没有打电话,那么
4) 子级扩展为假
5) 结束询问那个孩子
6) 移动到下一个孩子并再次询问
7) 直到所有孩子都被问到
【讨论】:
设置丢失的焦点似乎是最简单的方法。
Xaml:
<Expander LostFocus="CollapseExpander" ExpandDirection="Down" Width="175">
<ListBox Height="265" Margin="0,5,0,10">
</ListBox>
</Expander>
VB:
Private Sub CollapseExpander(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
sender.IsExpanded = False
End Sub
【讨论】:
使用 MVVM 并将 IsExpanded 属性绑定到视图模型上的布尔标志。当一个更新为true时,将所有其他设置为false。
【讨论】:
@wassim-azirar 询问接受的答案:
如何在应用程序启动时展开“扩展器 1”?
我在 ViewModel 中添加了:
SelectedExpander = "1";
因为“1”与 XAML 中的“1”不是同一个对象,所以这不起作用,所以我改变了 decyclone 的答案,如下所示:
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return (string)value == (string)parameter;
}
decyclone 的回答对我很有帮助 - 谢谢。
因此,如果有人需要,我想分享我的经验。
【讨论】:
试试 WPF Toolkit - February 2010 Release 的 Accordion 控件
http://www.dotnetspark.com/kb/1931-accordion-wpf-toolkit-tutorial.aspx
示例代码:
<my:Accordion x:Name="accordion1" VerticalAlignment="Top" HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" SelectionMode="ZeroOrOne">
<my:AccordionItem Header="First Header" Content="First Content"/>
<my:AccordionItem Header="Second Header">
<StackPanel Height="300">
<TextBlock Text="Second Content" /></StackPanel>
</my:AccordionItem>
<my:AccordionItem>
<my:AccordionItem.Header>
<TextBox Text="Third Item" />
</my:AccordionItem.Header>
<StackPanel Height="300">
<TextBlock Text="Third Item" />
</StackPanel>
</my:AccordionItem>
<my:AccordionItem>
<my:AccordionItem.Header>
<TextBlock Text="Fourth Item" />
</my:AccordionItem.Header>
<StackPanel Height="300">
<TextBlock Text="Third Item" />
</StackPanel>
</my:AccordionItem>
</my:Accordion>
【讨论】:
我也需要这个,但 IMO 的所有答案都太过分了。 这是我的做法:
每个人有 2 个事件
private void ex1_Collapsed(object sender, RoutedEventArgs e)
{
ex1.Height = 23.0;
}
private void ex1_Expanded(object sender, RoutedEventArgs e)
{
ex1.Height = 120.0;
ex2.IsExpanded = false;
ex3.IsExpanded = false;
}
它。
【讨论】: