代码改变世界

Windows Presentation Foundation(wpf) FAQ

  Clingingboy  阅读(1852)  评论(0编辑  收藏  举报

     这个帖子在微软官方的wpf讨论区http://forums.msdn.microsoft.com/en-US/wpf/thread/a2988ae8-e7b8-4a62-a34f-b851aaf13886
索性这个帖子是以前在我们博客园的同志sheva发的,不知道为何他建了一个新的bloghttp://shevaspace.blogspot.com/,不知道因为这篇blog的原因http://www.cnblogs.com/sheva/archive/2006/10/03/520583.html。。。。。So,有时间翻译翻译

3. 控件

3.1 如何展开TreeView 的所有节点(TreeViewItems) ?

不像Windows Forms,当前版本的WPF并没有提供以一行代码这样简单的方法来展开TreeView控件的所有节点。

一般而言,有两种方法可以实现这个功能.第一个方法是改变WPF 样式外观。以下xaml展示了这一方法:

<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#的辅助方法来展开所有节点

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) 
            { 
// Expand the current item. 
                currentContainer.IsExpanded = true; 
if (currentContainer.ItemContainerGenerator.Status != GeneratorStatus.ContainersGenerated) 
                { 
// If the sub containers of current item is not ready, we need to wait until 
// they are generated. 
                    currentContainer.ItemContainerGenerator.StatusChanged += delegate 
                    { 
                        ExpandSubContainers(currentContainer); 
                    }; 
                } 
else 
                { 
// If the sub containers of current item is ready, we can directly go to the next 
// iteration to expand them. 
                    ExpandSubContainers(currentContainer); 
                } 
            } 
        } 
    } 
}

The key to this technique shown above is to make sure that the container for the current TreeViewItem has been generated, so you can safely expand it to show all its sub items. That's why you need to make a recursive call when the status of current TreeViewItem's ItemContainerGenerator is GeneratorStatus.ContainersGenerated.

相关帖子:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2014662&SiteID=1
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=3180239&SiteID=1
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1130017&SiteID=1

3.2 如何在ListBox/ListView中实现拖拽?

Lasso selection is used quite often in most graphical editing programs, and it's a convenient way to select multiple on-screen objects. The following shows how to enable this type of selection to the WPF ListBox/ListView controls:

<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
{
// This field is used to tell if ListBox is in mouse selection mode.
private Boolean inMouseSelectionMode = false;
// This field is used to keep track of the current mouse selected items.
private List<ListBoxItem> selectedItems = new List<ListBoxItem>();
public Window1()
    {
        InitializeComponent();
    }
private void ListBoxItem_PreviewMouseUp(object sender, MouseButtonEventArgs e)
    {
// If the mouse is up, turn off "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;
// Highlight the currently mouse-overed item.
            mouseOverItem.SetValue(TextElement.ForegroundProperty, SystemColors.HighlightTextBrush);
if (!selectedItems.Contains(mouseOverItem))
            {
                selectedItems.Add(mouseOverItem);
            }
        }
    }
private void ListBoxItem_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
// When the mouse is down, we need to clear all previously mouse selected items.
        listBox.SelectedIndex = -1;
        inMouseSelectionMode = true;
foreach (ListBoxItem item in selectedItems)
        {
            item.ClearValue(ListBoxItem.BackgroundProperty);
            item.ClearValue(TextElement.ForegroundProperty);
        }
        selectedItems.Clear();
    }
} 

 

Related threads:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2443181&SiteID=1
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2427163&SiteID=1

3.3 How to implement RadioButtonList type of control in WPF?

WPF doesn't provide RadioButtonList control like ASP.NET does. Fortunately with WPF's powerful styling and templating capability, we could implement this type of control purely in XAML. Here is a XAMLPad ready example:

<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={RelativeSource TemplatedParent}}"
Content="{TemplateBinding Content}"/>
              </ControlTemplate>
            </Setter.Value>
          </Setter>
        </Style>
      </ListBox.ItemContainerStyle>
    </ListBox>
  </StackPanel>
</Page> 

Related threads:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=3023610&SiteID=1

编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
历史上的今天:
2007-07-06 ComponentArt控件分析之ComboBox(1)
点击右上角即可分享
微信分享提示