精华内容
下载资源
问答
  • 2021-05-22 16:01:20

    在 WPF 用的多的列表控件如 ListBox 或 ListView 等,本文告诉大家在这些列表控件上进行绑定多个数据集合来源的多个实现方法。如有一个显示动物列表的控件,需要绑定的数据来源是阿猫和阿狗两个 ObservableCollection 列表,不在后台代码编写合并集合的代码情况下,可以通过 XAML 的编写,绑定多个数据集合

    准备

    在开始之前,咱先搭建一点测试使用的代码,假定咱有一个 列表控件 准备绑定到的数据源是两个 ObservableCollection 对象,下面来定义这两个 ObservableCollection 对象和对应的 阿猫和阿狗 的代码

        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
    
                for (int i = 0; i < 10; i++)
                {
                    Dogs.Add(new Dog()
                    {
                        Name = "Dog" + i
                    });
    
                    Cats.Add(new Cat()
                    {
                        Name = "Cat" + i
                    });
                }
    
                DataContext = this;
            }
    
            public ObservableCollection<Dog> Dogs { get; } = new ObservableCollection<Dog>();
            public ObservableCollection<Cat> Cats { get; } = new ObservableCollection<Cat>();
        }
    
        public class Dog : Animal
        {
        }
    
        public class Cat : Animal
        {
        }
    
        public class Animal
        {
            public string Name { get; set; }
        }

    可以看到以上代码里面存在两个 ObservableCollection 对象,同时 MainWindow 的 DataContext 就是 MainWindow 对象。咱需要将两个 ObservableCollection 对象作为数据源,放在相同的一个 ListBox 里面

    下面是多个不同的实现方式,解决如何在 WPF 中在 ListBox 或 ListView 绑定多个数据集合 ObservableCollection 对象

    通过 CollectionViewSource 方式

    在 ListView 或 ListBox 资源里面,添加 CollectionViewSource 绑定到集合里面,然后在 ItemsSource 使用 CompositeCollection 进行绑定,代码如下

        <ListBox>
          <ListBox.Resources>
            <CollectionViewSource x:Key="DogCollection" Source="{Binding Dogs}"/>
            <CollectionViewSource x:Key="CatCollection" Source="{Binding Cats}"/>
          </ListBox.Resources>
          <ListBox.ItemsSource>
            <CompositeCollection>
              <CollectionContainer Collection="{Binding Source={StaticResource DogCollection}}"/>
              <CollectionContainer Collection="{Binding Source={StaticResource CatCollection}}"/>
            </CompositeCollection>
          </ListBox.ItemsSource>
    
          <ListBox.ItemTemplate>
            <DataTemplate>
              <TextBlock Text="{Binding Name}"></TextBlock>
            </DataTemplate>
          </ListBox.ItemTemplate>
    
        </ListBox>

    这个方法的优势在于可以完全使用 XAML 编写内容,但是缺点在于有重复的代码,如有多个绑定的集合对象,就需要在资源和 CompositeCollection 里面定义多个 CollectionViewSource 和 CollectionContainer 对象

    如果绑定的集合数量不多,那么此写法还成,但如果集合数量比较多,而且需要不断变更顺序,那以上写法就有坑

    此方法请参考 WPF 很少人知道的科技 - walterlv

    通过 CompositeCollection 动态绑定

    在 ListView 或 ListBox 的资源里面定义了 CompositeCollection 通过控件的 DataContext 绑定多个集合,代码如下

            <CompositeCollection x:Key="MyColl">
              <CollectionContainer Collection="{Binding DataContext.Dogs, Source={x:Reference MyList}}"/>
              <CollectionContainer Collection="{Binding DataContext.Cats, Source={x:Reference MyList}}"/>
            </CompositeCollection>

    以上代码的 MyList 就是集合控件,此方法需要用到 x:Reference 获取对象的引用,同时需要通过 DataContext 的某个属性获取到对应的属性,全部代码如下

        <ListBox x:Name="MyList" ItemsSource="{DynamicResource MyColl}">
          <ListBox.Resources>
            <CompositeCollection x:Key="MyColl">
              <CollectionContainer Collection="{Binding DataContext.Dogs, Source={x:Reference MyList}}"/>
              <CollectionContainer Collection="{Binding DataContext.Cats, Source={x:Reference MyList}}"/>
            </CompositeCollection>
          </ListBox.Resources>
          <ListBox.ItemTemplate>
            <DataTemplate>
              <TextBlock Text="{Binding Name}"></TextBlock>
            </DataTemplate>
          </ListBox.ItemTemplate>
        </ListBox>

    对比上面的方法,此方法可以让绑定集合的代码只写一次,看起来代码更少一点。但不足的地方在于绑定 ItemsSource 需要用到 DynamicResource 的方式,相对性能不如上面方法。为什么需要 DynamicResource 资源?原因是资源本身定义在 Resources 里面。为什么资源需要定义在控件里面的 Resource 里面?原因是为了获取到控件的 x:Reference 对象。也就是说需要在控件创建出来之后,才能通过 x:Reference 获取控件,而控件的数据内容需要依赖资源的定义,因此也只有以上方式的写法

    如果能从控件的上层容器拿到数据对象,那可以将资源定义在容器里面,通过 StaticResource 绑定到静态资源。如放在 Window 的 Resources 里

    <Window x:Class="CibairyafocairluYerkinemde.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:CibairyafocairluYerkinemde"
            mc:Ignorable="d"
            x:Name="Root"
            Title="MainWindow" Height="450" Width="800">
      <Window.Resources>
        <CompositeCollection x:Key="MyColl">
          <CollectionContainer Collection="{Binding DataContext.Dogs, Source={x:Reference Root}}"/>
          <CollectionContainer Collection="{Binding DataContext.Cats, Source={x:Reference Root}}"/>
        </CompositeCollection>
      </Window.Resources>
    
      <Grid>
       <ListBox x:Name="MyList" ItemsSource="{StaticResource MyColl}" >
          <ListBox.ItemTemplate>
            <DataTemplate>
              <TextBlock Text="{Binding Name}"></TextBlock>
            </DataTemplate>
          </ListBox.ItemTemplate>
        </ListBox>
      </Grid>
    </Window>

    以上写法没有啥缺点,也不存在动态资源的性能问题。但实际上在有动态资源下,性能问题也是很小的问题,对比渲染控件本身,动态绑定性能可以忽略

    通过多绑定方法

    此方法需要添加一点后台代码,定义 CompositeCollectionConverter 转换器,实现逻辑是通过多绑定的方法,将多个数据集合当成多个参数进行绑定

        <ListBox>
          <ListBox.ItemsSource>
            <MultiBinding Converter="{x:Static local:CompositeCollectionConverter.Default}">
              <Binding Path="Dogs" />
              <Binding Path="Cats" />
            </MultiBinding>
          </ListBox.ItemsSource>
          <ListBox.ItemTemplate>
            <DataTemplate>
              <TextBlock Text="{Binding Name}"></TextBlock>
            </DataTemplate>
          </ListBox.ItemTemplate>
        </ListBox>

    可以看到此方法的 XAML 代码量最小,只是需要一个辅助的 CompositeCollectionConverter 类,代码如下

        public class CompositeCollectionConverter : IMultiValueConverter
        {
            public static readonly CompositeCollectionConverter Default = new CompositeCollectionConverter();
    
            public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
            {
                var compositeCollection = new CompositeCollection();
                foreach (var value in values)
                {
                    if (value is IEnumerable enumerable)
                    {
                        compositeCollection.Add(new CollectionContainer { Collection = enumerable });
                    }
                    else
                    {
                        compositeCollection.Add(value);
                    }
                }
    
                return compositeCollection;
            }
    
            public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
            {
                throw new NotSupportedException("CompositeCollectionConverter ony supports oneway bindings");
            }
        }

    可以将 CompositeCollectionConverter 放在库里面,这样就可以让 XAML 代码看起来简单

    本文所有代码放在 githubgitee 欢迎小伙伴访问

    参考

    本文以上方法参考了如下博客

    c# - CompositeCollection + CollectionContainer: Bind CollectionContainer.Collection to property of ViewModel that is used as DataTemplates DataType - Stack Overflow

    wpf - How do you bind a CollectionContainer to a collection in a view model? - Stack Overflow

    WPF 很少人知道的科技 - walterlv

    我搭建了自己的博客 https://blog.lindexi.com/ 欢迎大家访问,里面有很多新的博客。只有在我看到博客写成熟之后才会放在csdn或博客园,但是一旦发布了就不再更新

    如果在博客看到有任何不懂的,欢迎交流,我搭建了 dotnet 职业技术学院 欢迎大家加入

    如有不方便在博客评论的问题,可以加我 QQ 2844808902 交流

    知识共享许可协议
    本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名林德熙(包含链接:http://blog.csdn.net/lindexi_gd ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系

    更多相关内容
  • WPF制作图表控件

    2018-07-13 10:22:59
    WPF一款制作图表的控件,下载完之后再直接安装,在VisualStudio的工具箱中会出现相应的图表控件,就可以添加图表。
  • c# wpf分页控件

    2019-06-03 17:24:42
    c# wpf分页控件,支持多选,自定义样式,一键引用,方便快捷
  • C# WPF ListView控件的实例详解 C#的WPF作为现在微软主流的桌面程序开发平台,相比过去的MFC时代,有了非常多的不同。本人刚从MFC平台转过来,以为可以轻松上手,哪知碰到了很多问题,十分不解。不得不乖乖回去看了...
  • 基于Toolkit ui组件进行的style 修改,这是一个比较酷的样式效果,也可以让朋友们知道怎么修改xctk:DateTimePicker 的样式,这个 Toolkit 可以在nuget 上直接安装,我在包了也放置了Toolkit 的源代码,并修复了它的...
  • 接触WPF也有两个多月了,有了一定的理论基础和项目经验,现在打算写一个系列,做出来一个WPF控件库。下面这篇文章主要给大家介绍了关于WPF自定义控件和样式之自定义按钮(Button)的相关资料,需要的朋友可以参考...
  • 本文提供了比WPF中包含的浏览器控件更好的浏览器控件
  • WPF自带的控件中只有Datepicker这个控件,不足以满足功能,鉴于WPF强大的自定义控件Usercontrol的功能,所以修改了一个支持选择日期时间控件---DateTimePicker,
  • WPF做的报表控件,小巧但实用。能够自定义表头,导出Excel表格和打印。
  • 这是一套开源且完整的WPF控件库,压缩包中包含了所有控件的使用案例,项目地址:https://github.com/HandyOrg/HandyControl
  • ListBox就是包含了列表的一个控件,我们用WPF程序来说明如何使用。 ListBox主要通过ListItem这个属性来创建元素,可以包括文本,图片和按钮等等其他控件,也可以包括一些布局面板。 我们可以通过ListBox的...

    WPF提供了许多包装集合的控件。这里包括了ListBox列表控件、ComboBox组合框控件,还有其他的更多的空间我们就不介绍了。

    1、ListBox

    ListBox就是包含了列表的一个控件,我们用WPF程序来说明如何使用。

    ListBox主要通过ListItem这个属性来创建元素,可以包括文本,图片和按钮等等其他控件,也可以包括一些布局面板。

    我们可以通过ListBox的SelectedIndex和SelectedItem属性访问选中对象的下标和选中的对象,我们创建三个复选框为例说明。

            private void listBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
            {
                if (listBox1.SelectedItem == null) return;
                this.textSelection.Text = "选择的选项为:" + (listBox1.SelectedIndex+1) + "\r\n"
                    + "选中状态为:" + ((CheckBox)listBox1.SelectedItem).IsChecked;
            }
    
            private void Button_Click(object sender, RoutedEventArgs e)
            {
                StringBuilder sb = new StringBuilder();
                foreach (CheckBox item in listBox1.Items)
                {
                    if (item.IsChecked == true)
                    {
                        sb.Append(item.Content);
                        sb.Append("被选中\r\n");
                    }
                    textSelection.Text = sb.ToString();
                }
            }

    当我们选中某个选项时,可以显示其选中的下标和内容,也可以通过访问选中的元素来看当前的复选框是否被选中的状态。 

     还可以添加按钮的响应事件,直接访问列表控件里面所有的元素,直接看是否被选中,并把结果输出:

    2、ComboBox

    ComboBox和ListBox类似,是通过ComboItem来对元素进行赋值。

    ComboBox同样也可以嵌套多种其他的控件,包括按钮,文本和图片等等。

    ComboBox和ListBox的区别在于,ComboBox是通过下拉框来选择元素,但是ListBox是都呈现出来了的,这里我们就不举例说明了。

     

    展开全文
  • 从国外开源网站上找到的效果非常好的WPF自定义控件。切换开关控件(WpfToggleSwitch)。
  • WPF .net Framework 4.6.2 虚拟键盘自定义控件;适合新手借鉴、程序应急使用;直接上源码,可自行修改; 虚拟键盘(支持英文,数字输入,及部分特殊字符(特殊字符都为英文字符)) 1.0版本;后续慢慢增加其他功能及其他...
  • 主要介绍了WPF滑块控件(Slider)的自定义样式的相关知识,本文给大家介绍的非常详细,具有一定的参考借鉴价值 ,需要的朋友可以参考下
  • wpf自定义控件库,包含列表,按钮,文本框,滚动条,进度条,消息窗体,气泡组件等多种自定义控件样式。
  • C# WPF控件中的文字旋转,可用于任何添加文字的控件,旋转角度可自定义
  • WPF 控件模板

    2022-02-16 09:38:53
    wpf的模板有多种方式,可以分为控件模板(ControlTemplate),控件列表模板(ItemsPanelTemplate)和数据模板(DataTemplate)。其中ControlTemplate和ItemsPanelTemplate都属于控件模板,但又有不同的表示。 1、...

    WPF 控件模板

    WPF中每个控件都被设计为无外观的,这意味着我们可以通过一定的方式,完全重定义其可视化外观,而WPF也提供了这种改变外观的方式之一,我们称为模板。wpf的模板有多种方式,可以分为控件模板(ControlTemplate),控件列表模板(ItemsPanelTemplate)和数据模板(DataTemplate)。其中ControlTemplate和ItemsPanelTemplate都属于控件模板,但又有不同的表示。

    1、控件模板(ControlTemplate)

    理解控件模板,首先得理解两个概念逻辑树和可视化树,逻辑树是我们最基本的要素列表,可视化树是逻辑书的扩展版本,它将元素分为更小的部分。换句话说说,逻辑树仅仅关心到控件级别,而可视化树关心到控件的组成的最基本图形元素。

    1.1 定义模板样式

    每个控件都有一个内置的方法,用于确定如何渲染控件,该方法称为控件模板,可以使用XAML标记块定义,下面我们定义一个普通的按钮的模板:

    <Button x:Name="btn1" Click="Button_Click" >
             <Button.Template >
                 <ControlTemplate >
                     <Grid >
                         <Ellipse Name="faceEllipse" Height="50" Width="100" Fill="{TemplateBinding Button.Background}"/>
                         <TextBlock Name="txtBlock"  Text="text" VerticalAlignment="Center" HorizontalAlignment="Center" />
                     </Grid >
                 </ControlTemplate >
             </Button.Template>
         </Button>

    效果如下:

    模板是控件的Template 属性,Template 是一个ControlTemplate对象,我们可以重定义这个对象,就是重新定义了按钮的界面,ControlTemplate里面可以使用任何控件,比如以下代码:

    <Button x:Name="btn1" Click="Button_Click" >
            <Button.Template >
                <ControlTemplate >
                    <Grid >
                        <Ellipse Name="faceEllipse" Height="50" Width="100" Fill="{TemplateBinding Button.Background}"/>
                        <TextBlock Name="txtBlock"  Text="text" VerticalAlignment="Center" HorizontalAlignment="Center" />
                        <CheckBox  IsChecked="True"></CheckBox>
                    </Grid >
                </ControlTemplate >
            </Button.Template>
        </Button>

    其效果如下:

    不过这种做法不常见,使用的时候需要谨慎处理。

    1.2 模板触发器

      触器是模板里面一个常用的功能,能为当前控件提供显示的多样性和多状态提供的触发机制,比如按钮,鼠标移上和鼠标移开,获取焦点和非焦点,都不一样,这些在不同状态下的显示,就需要触发器完成,触发器的详细讲解,请查看WPF触发器 - Min.Xiaoshuang - 博客园。控件模板触发器,基本能触发常规的触发器,属性和事件等。我们看看触发器如何使用:

    <Button x:Name="btn1" Click="Button_Click" >
             <Button.Template >
                 <ControlTemplate >
                     <Grid >
                         <Ellipse Name="faceEllipse" Height="50" Width="100" Fill="{TemplateBinding Button.Background}"/>
                         <TextBlock Name="txtBlock"  Text="text" VerticalAlignment="Center" HorizontalAlignment="Center" />
                     </Grid >
                     <ControlTemplate.Triggers >
                         <Trigger Property="Button.IsMouseOver" Value="True">
                             <Setter Property="Button.Background" Value="blue"/>
                         </Trigger >
                     </ControlTemplate.Triggers >
                 </ControlTemplate >
        
             </Button.Template>
         </Button>

    以上触发器,就是当前鼠标经过的时候,让按钮的背景变为蓝色,可以看到效果如下:

    1.3 模板的复用

    我们上面的案例,只是把模板放在按钮内部,那么只有这个按钮才能使用,为了实现共享模板等,我们可以把模板定义在resource里面,所以我们完全可以把以上代码添加到window.resource中,如以下代码:

    <Window.Resources>
          <ControlTemplate  x:Key="btntemp">
              <Grid >
                  <Ellipse Name="faceEllipse" Height="50" Width="100" Fill="{TemplateBinding Button.Background}"/>
                  <TextBlock Name="txtBlock"  Text="text" VerticalAlignment="Center" HorizontalAlignment="Center" />
              </Grid >
              <ControlTemplate.Triggers >
                  <Trigger Property="Button.IsMouseOver" Value="True">
                      <Setter Property="Button.Background" Value="blue"/>
                  </Trigger >
              </ControlTemplate.Triggers >
          </ControlTemplate >
      </Window.Resources>
      <Canvas>
          <Button x:Name="btn1" Click="Button_Click" Template="{StaticResource btntemp}"></Button>
      </Canvas>

    能实现以上相同功能,假如有多个按钮的话,则可以对模板进行复用,如果我们想当前窗体所有的按钮都统一样式,则可以指定 <ControlTemplate  x:Key="btntemp" TargetType="Button">,那么界面上所有的按钮(除非特别指定)都会使用当前样式。

    展开全文
  • WPF日期时间控件

    2018-09-05 09:12:45
    WPF日期时间控件,可选择日期和时间。日期时间格式自定义,用yyyy-MM-dd HH:mm:ss这样的字符串定义格式。有源代码。
  • WPF Thumb控件移动缩放

    2019-12-09 10:57:39
    WPF的Thumb实现控件的拖动,缩放。
  • wpf曲线控件

    2018-09-01 23:25:45
    自己工作中使用的非常好的wpf曲线控件,有用到这块的可以拿去直接使用。不是直接使用相关的参考也很有帮组,基本可以自己搞定。
  • WPF-自定义控件

    2017-05-18 18:24:40
    资源中包括自己写的控件和修改别人的集成到自己的控件。主要有:温度计控件、Win8转圈等待控件、车速仪表控件、微信圆球摆动控件、加载等待转圈控件等包括源码,欢迎下载
  • WPF 分页控件

    2020-11-03 10:33:52
    WPF 分页控件 主要读取图片文件列表 使用了图片水波效果 WPF 分页控件 主要读取图片文件列表 使用了图片水波效果
  • WPF实现控件的移动操作,实现大小拖动,位置移动,简单易学
  • WPF各种控件样式大全

    2017-11-21 16:44:56
    wpf 12种控件的Style 可能会需要修改 有Button,DataGrid,
  • WPF 自定义控件(包含全部代码) 自定义按钮、自定义文本框、自定义组合框、自定义日期控件等等
  • WPF 视频播放控件

    2018-12-19 11:40:41
    C# WPF 视频播放控件,支持播放、暂停、拖拽进度、调节音量大小等功能;
  • 一个可以实现年月日时分秒的WPF控件,希望对学习WPF的朋友有所帮助! 一个可以实现年月日时分秒的WPF控件,希望对学习WPF的朋友有所帮助!
  • wpf画图控件_Scichart

    热门讨论 2017-11-23 09:40:51
    wpf 画图控件 炫酷 破解 wpf 画图控件 炫酷 破解 wpf 画图控件 炫酷 破解 wpf 画图控件 炫酷 破解
  • WPF 界面 实现控件随着界面大小进行缩放,按住Ctrl按钮,然后混动混轮,就可以实现缩放了,控件比例和布局不变,会产生滚动条。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 51,734
精华内容 20,693
关键字:

wpf列表控件