1 怎样把TreeView中所以节点全部展开?
不同于Windows Forms,当前WPF版本没有提供一个直接的方法可以把TreeView控件所有的节点都展开。一般来说,在WPF中有两种方法可以实现这个功能。第一种方法就像下面例子一样使用样式展开所有节点:
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Page.Resources>
<XmlDataProvider x:Key="treeData" XPath="*">
<x:XData>
<Items Name="Items" xmlns="">
<Item1/>
<Item2>
<Item22/>
<Item12/>
<Item13>
<Item131/>
<Item131/>
</Item13>
</Item2>
</Items>
</x:XData>
</XmlDataProvider>
<HierarchicalDataTemplate ItemsSource="{Binding XPath=child::*}"
x:Key="template">
<TextBlock Name="textBlock" Text="{Binding Name}"/>
</HierarchicalDataTemplate>
</Page.Resources>
<TreeView ItemTemplate="{StaticResource template}"
ItemsSource="{Binding Source={StaticResource treeData}}">
<TreeView.ItemContainerStyle>
<!--Using style setter to set the TreeViewItem.IsExpanded property to true, this will be applied
to all TreeViweItems when they are generated-->
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsExpanded" Value="True"/>
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
</Page>
有些时候,你需要自己写代码去实现这个功能,下面的是用C#代码写成的一个帮助类可以展开TreeView控件中所有的节点:
public static class TreeViewHelper
{
public static void ExpandAll(TreeView treeView)
{
ExpandSubContainers(treeView);
}
private static void ExpandSubContainers(ItemsControl parentContainer)
{
foreach (Object item in parentContainer.Items)
{
TreeViewItem currentContainer = parentContainer.ItemContainerGenerator.ContainerFromItem(item) as TreeViewItem;
if (currentContainer != null && currentContainer.Items.Count > 0)
{
//展开当前节点
currentContainer.IsExpanded = true;
if (currentContainer.ItemContainerGenerator.Status != GeneratorStatus.ContainersGenerated)
{
//如果装入当前节点的容器还没有生成好,我们应该等待到它一直生成完成。
currentContainer.ItemContainerGenerator.StatusChanged += delegate
{
ExpandSubContainers(currentContainer);
};
}
else
{
//如果装入当前节点的容器已经生成,我们可以直接展开它。
ExpandSubContainers(currentContainer);
}
}
}
}
}
上面这个例子的关键之处就是要确认当前的TreeViewItem的容器已经生成了,所有你可以安全的展开当前节点的所有的子节点。这就是为什么你需要采用递归的方法(当前的节点ItemContainerGenerator状态是GeneratorStatus.ContainersGenerated.时)。
2 怎样在ListBox/ListView中实现多项选择?
(Lasso selection)在图形编辑程序中用得非常普遍,这种方法可以方便的选中屏幕上的多个对象。下面的这个例子展示了针对WPF的控件ListBox/ListView实现这个功能。
<ListBox Name="listBox"
Width="200"
Height="200"
SelectionMode="Multiple">
<ListBox.Resources>
<Style TargetType="{x:Type ListBoxItem}">
<EventSetter Event="ListBoxItem.PreviewMouseLeftButtonDown"
Handler="ListBoxItem_PreviewMouseLeftButtonDown"/>
<EventSetter Event="ListBoxItem.PreviewMouseUp"
Handler="ListBoxItem_PreviewMouseUp"/>
<EventSetter Event="ListBoxItem.PreviewMouseMove"
Handler="ListBoxItem_PreviewMouseMove"/>
</Style>
</ListBox.Resources>
<x:Type TypeName="DependencyObject"/>
<x:Type TypeName="Visual"/>
<x:Type TypeName="UIElement"/>
<x:Type TypeName="FrameworkElement"/>
<x:Type TypeName="Control"/>
</ListBox>
public partial class Window1 : Window
{
//这个字段用于显示ListBox是否是鼠标选择状态
private Boolean inMouseSelectionMode = false;
//这个字段用于与当前鼠标选择的项保持联系
private List<ListBoxItem> selectedItems = new List<ListBoxItem>();
public Window1()
{
InitializeComponent();
}
private void ListBoxItem_PreviewMouseUp(object sender, MouseButtonEventArgs e)
{
//若鼠标松开,则关闭"inMouseSelectionMode"
inMouseSelectionMode = false;
}
private void ListBoxItem_PreviewMouseMove(object sender, MouseEventArgs e)
{
ListBoxItem mouseOverItem = sender as ListBoxItem;
if (mouseOverItem != null && inMouseSelectionMode && e.LeftButton ==MouseButtonState.Pressed)
{
mouseOverItem.Background = SystemColors.HighlightBrush;
//高亮显示当前位于鼠标下方的项
mouseOverItem.SetValue(TextElement.ForegroundProperty,SystemColors.HighlightTextBrush);
if (!selectedItems.Contains(mouseOverItem))
{
selectedItems.Add(mouseOverItem);
}
}
}
private void ListBoxItem_PreviewMouseLeftButtonDown(object sender,MouseButtonEventArgs e)
{
//当鼠标点击时,我们需要消除所有先前选中的项
listBox.SelectedIndex = -1;
inMouseSelectionMode = true;
foreach (ListBoxItem item in selectedItems)
{
item.ClearValue(ListBoxItem.BackgroundProperty);
item.ClearValue(TextElement.ForegroundProperty);
}
selectedItems.Clear();
}
}
3 怎样实现单选列表控件?
WPF没有像ASP.NET提供一个RadioButtonList的控件。幸运的是,我们可以利用WPF样式和模板的强大功能,用纯粹的XAML代码实现这个功能,下面是一个在XAMLPad可运行的例子:
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="clr-namespace:System;assembly=mscorlib">
<Page.Resources>
<x:Array Type="{x:Type s:String}" x:Key="data">
<s:String>Option1</s:String>
<s:String>Option2</s:String>
<s:String>Option3</s:String>
</x:Array>
</Page.Resources>
<StackPanel DataContext="{StaticResource data}">
<TextBlock Margin="5">
<TextBlock Text="Current Option:"/>
<TextBlock Text="{Binding /}"/>
</TextBlock>
<ListBox
ItemsSource="{Binding}"
IsSynchronizedWithCurrentItem="True"
Width="240"
Height="60"
HorizontalAlignment="Left">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<RadioButton
IsChecked="{Binding Path=IsSelected, RelativeSource={RelativeSourceTemplatedParent}}"
Content="{TemplateBinding Content}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
</StackPanel>
</Page>
原文地址:
http://silverlightchina.net/html/study/WPF/2012/0904/18642.html