WPF集合绑定与数据模板

普通List集合数据绑定

在数据源中建立一个list数组,设置ListBox的ItemsSource属性指定list数组

    public class DataSource
    {
        public string Name { get; set; } = "Hello";

        public ObservableCollection<string> list { get; set; } =
            new ObservableCollection<string>()
            {
                { "AAA"},
                { "BBB"},
                { "CCC"},
            };
    }
    <Window.DataContext>
        <local:DataSource/>
    </Window.DataContext>
    <StackPanel>
        <TextBlock Text="{Binding Name}"/>
        <ListBox ItemsSource="{Binding list}" Name="lb"/>
    </StackPanel>

设置子项的数据绑定模板

使用泛型创建一组DataItem类型数组。在WPF中需要设置数据模板DataTemplate,指定每列TextBlock需要显示的具体数据。

Binding Header的展开式

DataContext.Name,RelativeSource={RelativeSource AncestorType=ListBox}

    public class DataSource
    {
        public string Name { get; set; } = "Hello";

        public ObservableCollection<DataItem> list { get; set; } =
            new ObservableCollection<DataItem>()
            {
                new DataItem{ id=1,Header="AAA",State=0},
                new DataItem{ id=2,Header="BBB",State=1},
                new DataItem{ id=3,Header="CCC",State=0},
            };
    }

    public class DataItem
    {
        public int id { get; set; }
        public string Header { get; set; }
        public int State { get; set; }
    }
    <Window.DataContext>
        <local:DataSource/>
    </Window.DataContext>
    <StackPanel>
        <TextBlock Text="{Binding Name}"/>
        <ListBox ItemsSource="{Binding list}" Name="lb">
            <!--子项模板-->
            <ListBox.ItemTemplate>
                <!--数据模板-->
                <DataTemplate>
                    <StackPanel Orientation="Horizontal" TextBlock.Foreground="Gray" Name="sp">
                        <TextBlock Text="{Binding id}" Margin="10,0"/>
                        <TextBlock Text="{Binding Header}" Margin="10,0"/>
                        <TextBlock Text="{Binding DataContext.Name,RelativeSource={RelativeSource AncestorType=ListBox}}" Margin="10,0"/>
                        <TextBlock Text="{Binding DataContext.Name,ElementName=lb}" Margin="10,0"/>
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </StackPanel>

数据模板触发器

    <!--<Window.DataContext>
        <local:DataSource/>
    </Window.DataContext>-->
    <StackPanel>
        <TextBlock Text="{Binding Name}"/>
        <ListBox ItemsSource="{Binding list}" Name="lb">
            <!--子项模板-->
            <ListBox.ItemTemplate>
                <!--数据模板-->
                <DataTemplate>
                    <StackPanel Orientation="Horizontal" TextBlock.Foreground="Gray" Name="sp">
                        <TextBlock Text="{Binding id}" Margin="10,0"/>
                        <TextBlock Text="{Binding Header}" Margin="10,0"/>
                        <TextBlock Text="{Binding DataContext.Name,RelativeSource={RelativeSource AncestorType=ListBox}}" Margin="10,0"/>
                        <TextBlock Text="{Binding DataContext.Name,ElementName=lb}" Margin="10,0"/>
                        <TextBlock Text="{Binding State}"/>
                        <Button Content="处理" Name="btn" Visibility="Collapsed"/>
                    </StackPanel>
                    <DataTemplate.Triggers>
                        <!--<Trigger Property = "IsChecked" Value="True"> 判断的是对象的基本属性-->
                        <!--<DataTrigger 判断的是数据源中的数据属性-->
                        <!--数据模板选择器-->
                        <DataTrigger Binding="{Binding State}" Value="1">
                            <Setter TargetName="sp" Property="TextBlock.Foreground" Value="Red"/>
                            <Setter TargetName="btn" Property="Visibility" Value="Visible"/>
                        </DataTrigger>
                    </DataTemplate.Triggers>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
        <Button Content="Button" Click="Button_Click"/>
    </StackPanel>

数据模板选择器

    public class MyDataTemplateSelector : DataTemplateSelector
    {
        public DataTemplate NoramlTemplate { get; set; }
        public DataTemplate WarningTemplate { get; set; }

        public override DataTemplate SelectTemplate(object item, DependencyObject container)
        {
            var di = item as DataItem;

            if (di.State == 1)
                return WarningTemplate;

            return NoramlTemplate;
        }
    }
    <Window.Resources>
        <DataTemplate x:Key="dt1">
            <StackPanel Orientation="Horizontal" TextBlock.Foreground="Gray" Name="sp">
                <TextBlock Text="{Binding id}" Margin="10,0"/>
                <TextBlock Text="{Binding Header}" Margin="10,0"/>
                <TextBlock Text="{Binding DataContext.Name,RelativeSource={RelativeSource AncestorType=ListBox}}" Margin="10,0"/>
                <TextBlock Text="{Binding DataContext.Name,ElementName=lb}" Margin="10,0"/>
                <TextBlock Text="{Binding State}"/>
            </StackPanel>
        </DataTemplate>
        <DataTemplate x:Key="dt2">
            <StackPanel Orientation="Horizontal" TextBlock.Foreground="Red" Name="sp">
                <TextBlock Text="{Binding id}" Margin="10,0"/>
                <TextBlock Text="{Binding Header}" Margin="10,0"/>
                <TextBlock Text="{Binding DataContext.Name,RelativeSource={RelativeSource AncestorType=ListBox}}" Margin="10,0"/>
                <TextBlock Text="{Binding DataContext.Name,ElementName=lb}" Margin="10,0"/>
                <TextBlock Text="{Binding State}"/>
                <Button Content="处理" Name="btn"/>
            </StackPanel>
        </DataTemplate>

        <local:MyDataTemplateSelector x:Key="mdts"
                                      NoramlTemplate="{StaticResource dt1}"
                                      WarningTemplate="{StaticResource dt2}"/>
    </Window.Resources>

    <StackPanel>
        <TextBlock Text="{Binding Name}"/>
        <ListBox ItemsSource="{Binding list}" Name="lb">
            <!--子项模板-->
            <ListBox.ItemTemplate>
                <!--数据模板-->
                <DataTemplate>
                    <StackPanel Orientation="Horizontal" TextBlock.Foreground="Gray" Name="sp">
                        <TextBlock Text="{Binding id}" Margin="10,0"/>
                        <TextBlock Text="{Binding Header}" Margin="10,0"/>
                        <TextBlock Text="{Binding DataContext.Name,RelativeSource={RelativeSource AncestorType=ListBox}}" Margin="10,0"/>
                        <TextBlock Text="{Binding DataContext.Name,ElementName=lb}" Margin="10,0"/>
                        <TextBlock Text="{Binding State}"/>
                        <Button Content="处理" Name="btn" Visibility="Collapsed"/>
                    </StackPanel>
                    <DataTemplate.Triggers>
                        <!--<Trigger Property = "IsChecked" Value="True"> 判断的是对象的基本属性-->
                        <!--<DataTrigger 判断的是数据源中的数据属性-->
                        <!--数据模板选择器-->
                        <DataTrigger Binding="{Binding State}" Value="1">
                            <Setter TargetName="sp" Property="TextBlock.Foreground" Value="Red"/>
                            <Setter TargetName="btn" Property="Visibility" Value="Visible"/>
                        </DataTrigger>
                    </DataTemplate.Triggers>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
        <Button Content="Button" Click="Button_Click"/>

        <ListBox ItemsSource="{Binding list}">
            <ListBox.ItemTemplateSelector>
                <local:MyDataTemplateSelector 
                    WarningTemplate="{StaticResource dt2}" 
                    NoramlTemplate="{StaticResource dt1}"/>
            </ListBox.ItemTemplateSelector>
        </ListBox>

        <ListBox ItemsSource="{Binding list}" ItemTemplateSelector="{StaticResource mdts}"/>
    </StackPanel>

将模板实例传到MyDataTemplateSelector,设置ListBox的ItemTemplateSelector属性引用MyDataTemplateSelector,自动判断使用哪种模板。

ListView、DataGrid、TreeView

    public class DataSource
    {
        // 静态属性

        public string Name { get; set; } = "Hello";


        public object CurrentItem { get; set; }
        public int CurrentId { get; set; }

        public ObservableCollection<DataItem> list { get; set; } =
            new ObservableCollection<DataItem>()
            {
                new DataItem{ id=1,Header="AAA",State=0},
                new DataItem{ id=2,Header="BBB",State=1},
                new DataItem{ id=3,Header="CCC",State=0},
            };


        public DataSource()
        {
            list[0].Children.Add(new DataItem { Header = "AAA-1"});
            list[0].Children.Add(new DataItem { Header = "AAA-2"});

            list[1].Children.Add(new DataItem { Header = "BBB-1" });
            list[1].Children.Add(new DataItem { Header = "BBB-2" });

            list[2].Children.Add(new DataItem { Header = "CCC-1" });
            list[2].Children.Add(new DataItem { Header = "CCC-2" });


            list[0].Children[0].Children.Add(new DataItem { Header = "AAA-1-1" });
        }


    }

    public class DataItem
    {
        public string Icon { get; set; }
        public int id { get; set; }
        public string Header { get; set; }
        public int State { get; set; }

        public List<DataItem> Children { get; set; } = new List<DataItem>();

        // 自己嵌套自己  无限层级
    }
    <Window.DataContext>
        <local:DataSource/>
    </Window.DataContext>
    <StackPanel>
        <!--第二类-->
        <ListView ItemsSource="{Binding list}">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="ID" DisplayMemberBinding="{Binding id}"/>
                    <GridViewColumn Header="Name" DisplayMemberBinding="{Binding Header}"/>
                </GridView>
            </ListView.View>
        </ListView>
        <DataGrid ItemsSource="{Binding list}" AutoGenerateColumns="False" CanUserAddRows="False">
            <DataGrid.Columns>
                <DataGridTextColumn Header="编号" Binding="{Binding id}"/>
                <DataGridTextColumn Header="名称" Binding="{Binding Header}"/>
            </DataGrid.Columns>
        </DataGrid>

        <!--第三类-->
        <TreeView ItemsSource="{Binding list}">
            <TreeView.ItemTemplate>
                <HierarchicalDataTemplate ItemsSource="{Binding Children}">
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="auto"/>
                            <ColumnDefinition Width="auto"/>
                        </Grid.ColumnDefinitions>
                        <TextBlock Text="@"/>
                        <TextBlock Text="{Binding Header}" Grid.Column="1"/>
                    </Grid>
                </HierarchicalDataTemplate>
            </TreeView.ItemTemplate>
        </TreeView>
    </StackPanel>

ItemsControl、ListBox

    /// <summary>
    /// ColumnChartWindow.xaml 的交互逻辑
    /// </summary>
    public partial class ColumnChartWindow : Window
    {
        ChartDataSource cds = new ChartDataSource();
        public ColumnChartWindow()
        {
            InitializeComponent();

            this.DataContext = cds;
        }
        ~ColumnChartWindow()
        {
            cds.Dispose();
        }
    }
    public class ChartDataSource
    {
        public ObservableCollection<ColumnItem> datas { get; set; } =
            new ObservableCollection<ColumnItem>();
        CancellationTokenSource cts = new CancellationTokenSource();
        Task task;
        public ChartDataSource()
        {
            for (int i = 0; i < 15; i++)
            {
                datas.Add(new ColumnItem
                {
                    Value = new Random().Next(10, 200),
                    LabelText = DateTime.Now.ToString("mm:ss")
                });
            }
            task = Task.Run(async () =>
            {
                while (!cts.IsCancellationRequested)
                {
                    await Task.Delay(1000);
                    // 出错
                    try
                    {
                        //ObservableCollection这个类型的数据,会导致界面的对象渲染变更(控件的增减)
                        // 界面上的操作都需要在UI线程(主线程)处理
                        // Task属于子线程(后台线程,不是主线程)

                        Application.Current.Dispatcher.Invoke(() =>
                        {
                            datas.Add(new ColumnItem()
                            {
                                Value = new Random().Next(10, 200),
                                LabelText = DateTime.Now.ToString("mm:ss")
                            });

                            if (datas.Count > 20)
                                datas.RemoveAt(0);
                        });
                    }
                    catch (Exception ex)
                    {

                    }
                }
            }, cts.Token);
        }
        ~ChartDataSource()
        {

        }
        public void Dispose()
        {
            // 销毁线程

            cts.Cancel();
            task.Wait(5000);
        }
    }
    public class ColumnItem
    {
        public string LabelText { get; set; }
        public int Value { get; set; }
    }
<Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <ItemsControl ItemsSource="{Binding datas}">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <VirtualizingStackPanel Orientation="Horizontal"/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition/>
                            <RowDefinition Height="auto"/>
                        </Grid.RowDefinitions>
                        <Border Height="1" Background="Gray" VerticalAlignment="Bottom"/>
                        <Border Width="12" Height="{Binding Value}" Background="Orange" VerticalAlignment="Bottom" Margin="0,0,0,1"/>
                        <TextBlock Text="{Binding LabelText}" Grid.Row="1" Margin="5,0"/>
                    </Grid>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>

        <ListBox ItemsSource="{Binding datas}" Grid.Row="1">
            <ListBox.ItemContainerStyle>
                <Style TargetType="ListBoxItem">
                    <!--<Setter Property="VerticalContentAlignment" Value="Bottom"/>-->
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="ListBoxItem">
                                <Border Background="{TemplateBinding Background}">
                                    <ContentPresenter/>
                                </Border>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                    <Style.Triggers>
                        <Trigger Property="IsSelected" Value="True">
                            <Setter Property="Background" Value="Gray"/>
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </ListBox.ItemContainerStyle>
            <ListBox.ItemsPanel>
                <ItemsPanelTemplate>
                    <VirtualizingStackPanel Orientation="Horizontal"/>
                </ItemsPanelTemplate>
            </ListBox.ItemsPanel>
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition/>
                            <RowDefinition Height="auto"/>
                        </Grid.RowDefinitions>
                        <Border Height="1" Background="Gray" VerticalAlignment="Bottom"/>
                        <Border Width="12" Height="{Binding Value}" Background="Orange" VerticalAlignment="Bottom" Margin="0,0,0,1"/>
                        <TextBlock Text="{Binding LabelText}" Grid.Row="1" Margin="5,0"/>
                    </Grid>
                </DataTemplate>
            </ListBox.ItemTemplate>

        </ListBox>
    </Grid>

ComboBox

    public class MultiLevelDataSource : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler? PropertyChanged;
        // 列表中的子项数据:id\Header\ParentId
        public List<Area> AreaAll { get; set; } = new List<Area>();
        public int CurrentCIndex { get; set; } = 0;
        public int CurrentDIndex { get; set; } = 0;

        private int _currentPCode;
        public int CurrentPCode
        {
            get => _currentPCode;
            set
            {
                _currentPCode = value;
                var cs = AreaAll.Where(a => a.ParentCode == value).ToList();
                CityList.Clear();
                foreach (var item in cs)
                {
                    CityList.Add(item);
                }
                var ds = AreaAll.Where(a => a.ParentCode == CityList[0].Code).ToList();
                DistrictList.Clear();
                foreach (var item in ds)
                {
                    DistrictList.Add(item);
                }
                //CurrentCIndex = 0;
                //CurrentDIndex = 0;
                //PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("CurrentCIndex"));
                //PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("CurrentDIndex"));
            }
        }
        private int _currentCity;
        public int CurrentCCode
        {
            get => _currentCity;
            set
            {
                _currentCity = value;
                var ds = AreaAll.Where(a => a.ParentCode == value).ToList();
                DistrictList.Clear();
                foreach (var item in ds)
                {
                    DistrictList.Add(item);
                }
                //CurrentDIndex = 0;
                //PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("CurrentDIndex"));
            }
        }
        public int CurrentDCode { get; set; }
        public ObservableCollection<Area> ProvinceList { get; set; }
        public ObservableCollection<Area> CityList { get; set; }
        public ObservableCollection<Area> DistrictList { get; set; }
        public MultiLevelDataSource()
        {
            ProvinceList = new ObservableCollection<Area>();
            CityList = new ObservableCollection<Area>();
            DistrictList = new ObservableCollection<Area>();
            Task.Run(async () =>
            {
                await Task.Delay(1000); // 耗时操作
                // 获取到数据后,进行页面初始化
                AreaAll.Add(new Area { Code = 1, Header = "湖北", ParentCode = 0 });
                AreaAll.Add(new Area { Code = 2, Header = "江苏", ParentCode = 0 });
                AreaAll.Add(new Area { Code = 3, Header = "武汉", ParentCode = 1 });
                AreaAll.Add(new Area { Code = 4, Header = "襄阳", ParentCode = 1 });
                AreaAll.Add(new Area { Code = 5, Header = "南京", ParentCode = 2 });
                AreaAll.Add(new Area { Code = 6, Header = "苏州", ParentCode = 2 });
                AreaAll.Add(new Area { Code = 7, Header = "武昌", ParentCode = 3 });
                AreaAll.Add(new Area { Code = 8, Header = "洪山", ParentCode = 3 });
                AreaAll.Add(new Area { Code = 9, Header = "江岸", ParentCode = 3 });
                AreaAll.Add(new Area { Code = 10, Header = "襄城", ParentCode = 4 });
                AreaAll.Add(new Area { Code = 11, Header = "樊成", ParentCode = 4 });
                AreaAll.Add(new Area { Code = 12, Header = "襄州", ParentCode = 4 });
                AreaAll.Add(new Area { Code = 13, Header = "玄武", ParentCode = 5 });
                AreaAll.Add(new Area { Code = 14, Header = "建邺", ParentCode = 5 });
                AreaAll.Add(new Area { Code = 15, Header = "鼓楼", ParentCode = 5 });
                AreaAll.Add(new Area { Code = 16, Header = "姑苏", ParentCode = 6 });
                AreaAll.Add(new Area { Code = 17, Header = "相城", ParentCode = 6 });
                AreaAll.Add(new Area { Code = 18, Header = "吴中", ParentCode = 6 });

                Application.Current.Dispatcher.Invoke(() =>
                {
                    var ps = AreaAll.Where(a => a.ParentCode == 0).ToList();
                    foreach (var item in ps)
                    {
                        ProvinceList.Add(item);
                    }
                    //var cs = AreaAll.Where(a => a.ParentCode == ProvinceList[0].Code).ToList();
                    //foreach (var item in cs)
                    //{
                    //    CityList.Add(item);
                    //}
                    //var ds = AreaAll.Where(a => a.ParentCode == CityList[0].Code).ToList();
                    //foreach (var item in ds)
                    //{
                    //    DistrictList.Add(item);
                    //}
                    CurrentPCode = 2; CurrentCCode = 5; CurrentDCode = 13;
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("CurrentPCode"));
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("CurrentCCode"));
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("CurrentDCode"));
                });
                //CurrentCIndex = 0;
                //CurrentDIndex = 0;
                //PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("CurrentCIndex"));
                //PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("CurrentDIndex"));
            });
        }
    }
    public class Area
    {
        public int Code { get; set; }
        public string Header { get; set; }
        public int ParentCode { get; set; }
    }
    <Window.DataContext>
        <local:DataSource/>
    </Window.DataContext>
    <StackPanel>
        <ComboBox Width="200" Height="45" VerticalAlignment="Top"
                  ItemsSource="{Binding list}" SelectedIndex="0"
                  DisplayMemberPath="Header"
                  SelectedValuePath="id"
                  SelectedValue="{Binding CurrentId}"
                  SelectedItem="{Binding CurrentItem}">
        </ComboBox>
        <!--DisplayMemberPath="Header"   这种设置因为数据源是复杂类型  List<string>-->
        <!--SelectedItem  对应的是ComboBoxItem的子项-->
        <ComboBox Width="200" Height="45" VerticalAlignment="Top"
                  SelectedIndex="0"               
                  
                  SelectedItem="{Binding CurrentItem}">
            <ComboBoxItem>
                <TextBlock Text="AAA"/>
            </ComboBoxItem>
            <ComboBoxItem>
                <TextBlock Text="BBB"/>
            </ComboBoxItem>
        </ComboBox>
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
            <StackPanel.DataContext>
                <local:MultiLevelDataSource/>
            </StackPanel.DataContext>
            <ComboBox Width="200" Height="45" ItemsSource="{Binding ProvinceList}"
                      SelectedIndex="0"
                      DisplayMemberPath="Header"
                      SelectedValuePath="Code"
                      SelectedValue="{Binding CurrentPCode}"/>
            <ComboBox Width="200" Height="45" ItemsSource="{Binding CityList}"
                      SelectedIndex="{Binding CurrentCIndex}"
                      DisplayMemberPath="Header"
                      SelectedValuePath="Code"
                      SelectedValue="{Binding CurrentCCode}"/>
            <ComboBox Width="200" Height="45" ItemsSource="{Binding DistrictList}"
                      SelectedIndex="{Binding CurrentDIndex}"
                      DisplayMemberPath="Header"
                      SelectedValuePath="Code"
                      SelectedValue="{Binding CurrentDCode}"/>
        </StackPanel>
    </StackPanel>

posted @ 2023-11-25 10:49  ZHIZRL  阅读(422)  评论(0编辑  收藏  举报