您的位置:首页 > 其它

WPF 之使用Treeview和DataGrid的关联绑定

2017-08-04 15:53 459 查看
实现功能:WPF通过读取XML数据绑定到TreeView, 在通过TreeView选择项(Node)获取的对应的数据绑定到DataGrid控件上,再通过DataGrid选中行的详细信息数据绑定到另一个DataGrid。

首先创建XML数据. 名称为 Order.xml

<?xml version="1.0" encoding="utf-8" ?>
<root>
<category name="Computer">
<product name="联想笔记本">
<order orderId="1" orderName="cizon的订单" orderDate="2012-11-10">
<orderInfo productName="联想笔记本" unitPrice="3000" count="2">
</orderInfo>
</order>
<order orderId="2" orderName="steven的订单" orderDate="2012-11-10">
<orderInfo productName="联想笔记本" unitPrice="3000" count="2">
</orderInfo>
</order>
</product>
<product name="宏基笔记本">
<order orderId="1" orderName="Luly的订单" orderDate="2012-11-10">
<orderInfo productName="宏基笔记本" unitPrice="2000" count="3">
</orderInfo>
</order>
<order orderId="2" orderName="steven的订单" orderDate="2012-11-10">
<orderInfo productName="宏基笔记本" unitPrice="2000" count="3">
</orderInfo>
</order>
</product>
<product name="华硕笔记本"></product>
</category>
<category name="TV">
<product name="海尔电视">
<order orderId="1" orderName="cizon的订单" orderDate="2012-11-10">
<orderInfo productName="海尔电视" unitPrice="1000" count="2">
</orderInfo>
</order>
<order orderId="2" orderName="steven的订单" orderDate="2012-11-10">
<orderInfo productName="海尔电视" unitPrice="1000" count="2">
</orderInfo>
</order>
</product>
<product name="长虹电视">
<order orderId="1" orderName="Luly的订单" orderDate="2012-11-10">
<orderInfo productName="长虹电视" unitPrice="2000" count="3">
</orderInfo>
</order>
<order orderId="2" orderName="steven的订单" orderDate="2012-11-10">
<orderInfo productName="长虹电视" unitPrice="2000" count="3">
</orderInfo>
</order>
</product>
<product name="三星电视"></product>
</category>
</root>


创建Model实体类:

public class Category
{
public string Name { get; set; }
public List<Product> Products { get; set; }
}

public class Product
{
public string Name { get; set; }
public List<Order> Orders { get; set; }
}

public class Order
{
public int OrderId { get; set; }
public string OrderName { get; set; }
public DateTime OrderDate { get; set; }
public decimal TotalPrice { get; set; }
public List<OrderInfo> OrderInfos { get; set; }
}

public  class OrderInfo
{
public int OrderId { get; set; }
public string ProductName { get; set; }
public decimal UnitPrice { get; set; }
public int Count { get; set; }
}


创建数据访问类GetData 获取XML中数据:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace WpfApplication1
{
public class GetData
{
//private string path = AppDomain.CurrentDomain.SetupInformation.ApplicationBase + "OrderData.xml";
private string path = "../../OrderData.xml";
public List<Category> GetCategorys()
{
XElement xElement = XElement.Load(path);
var categorys = (from n in xElement.Elements("category")
select new Category
{
Name = n.Attribute("name").Value,
Products = GetProducts(n)
}).ToList();
return categorys;
}

private List<Product> GetProducts(XElement xElement)
{
var products = (from n in xElement.Elements("product")
select new Product
{
Name = n.Attribute("name").Value,
Orders = GetOrders(n)
}).ToList();
return products;
}

private List<Order> GetOrders(XElement xElement)
{
var orders = (from n in xElement.Elements("order")
select
new Order
{
OrderId = Convert.ToInt32(n.Attribute("orderId").Value),
OrderName = n.Attribute("orderName").Value,
OrderDate = Convert.ToDateTime(n.Attribute("orderDate").Value),
TotalPrice = GetTotalPrice(n),
OrderInfos = GetOrderInfo(n)
}).ToList();
return orders;
}

private decimal GetTotalPrice(XElement xElement)
{
decimal totalPrice = 0;
List<OrderInfo> orderInfos = GetOrderInfo(xElement);
foreach (var info in orderInfos)
{
totalPrice += info.UnitPrice * info.Count;
}
return totalPrice;
}

private List<OrderInfo> GetOrderInfo(XElement xElement)
{
var orderInfos = (from n in xElement.Elements("orderInfo")
select
new OrderInfo
{
OrderId = Convert.ToInt32(n.Parent.Attribute("orderId").Value),
ProductName = n.Attribute("productName").Value,
UnitPrice = Convert.ToDecimal(n.Attribute("unitPrice").Value),
Count = Convert.ToInt32(n.Attribute("count").Value)
}).ToList();
return orderInfos;
}
}
}


加载的DLL程序集为



创建一个ViewModel类实现INotifyPropertyChanged接口通知属性值得改变,实现双向绑定,

public class ViewModel:INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
GetData getData=new GetData();
private List<Category> _categories;
public List<Category> GetCategories
{
get
{
if(_categories==null)
{
_categories = getData.GetCategorys();
}
return _categories;

}
set
{
if(value!=_categories)
{
_categories = value;
if(PropertyChanged!=null)
{
PropertyChanged(this, new PropertyChangedEventArgs("GetCategories"));
}
}
}
}
}


窗体页面绑定代码

<Window x:Class="WpfApplication1.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:WpfApplication1"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:ViewModel></local:ViewModel>
</Window.DataContext>
<Window.Resources>
<HierarchicalDataTemplate x:Key="treeData" ItemsSource="{Binding Path=Products}">
<TextBlock  Text="{Binding Path=Name}"/>
</HierarchicalDataTemplate>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="180"></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="10"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>

<TreeView Name="tree" ItemsSource="{Binding GetCategories}" ItemTemplate="{StaticResource ResourceKey=treeData}" Grid.RowSpan="3"/>
<DataGrid Name="dataGrid1" AutoGenerateColumns="False" ItemsSource="{Binding ElementName=tree, Path=SelectedItem.Orders}" Grid.Column="2">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding OrderId}" Width="*" Header="订单编号"></DataGridTextColumn>
<DataGridTextColumn Binding="{Binding OrderName}" Width="*" Header="订单名称"></DataGridTextColumn>
<DataGridTextColumn Binding="{Binding OrderDate}" Width="*" Header="订单时间"></DataGridTextColumn>
<DataGridTextColumn Binding="{Binding TotalPrice}" Width="*" Header="总额"></DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
<DataGrid Name="dataGrid2" AutoGenerateColumns="False" ItemsSource="{Binding ElementName='dataGrid1', Path=SelectedItem.OrderInfos}" Grid.Column="2" Grid.Row="2">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding OrderId}" Width="*" Header="订单编号"></DataGridTextColumn>
<DataGridTextColumn Binding="{Binding ProductName}" Width="*" Header="产品"></DataGridTextColumn>
<DataGridTextColumn Binding="{Binding UnitPrice}" Width="*" Header="单价"></DataGridTextColumn>
<DataGridTextColumn Binding="{Binding Count}" Width="*" Header="数量"></DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>


后台代码

/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
private ViewModel _viewModel;
public MainWindow()
{
InitializeComponent();
_viewModel = new ViewModel();
this.DataContext = _viewModel;
}


其中Window.Datacontext的标记是可以注释掉的。



整个项目的结构是这样子滴



接下来运行起来, 看看效果.







好了,今天到此为止了。 博主也是刚开始学习WPF呢。 好多都不懂。 本篇文章参考自http://www.cnblogs.com/cizon/archive/2012/11/11/2765596.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  xml treeview datagrid wpf