天天看點

黑馬程式員 C#學習筆記⑤ 省市縣三級關聯查詢

---------------------- ASP.Net+Unity開發、 .Net教育訓練、期待與您交流! ----------------------詳細請檢視: www.itheima.com

實作一個可以動态的進行省市縣查詢的程式

一 基本原理: 通過ADO.NET技術查詢資料庫, 并綁定到WPF控件中, 進而實作動态的省市縣查詢.

二 實作技術:

ADO.NET

資料綁定

三 實作步驟:

①首先進行資料庫建立, 在網上下載下傳一個省市縣的資料庫腳本. 部分内容如下圖:

黑馬程式員 C#學習筆記⑤ 省市縣三級關聯查詢

以上腳本建立了一個名叫AreaFull的表, 表中存儲了個省市的資訊.

AreaId----------表示該區域的Id

AreaName----表示該區域的名稱

AreaPid--------表示該區域的直屬上級區域

② 建立了資料庫後, 在vs中使用ADO.NET技術來使用它.

先在App.Config中定義連接配接字元串

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
  <connectionStrings>
    <add name="dbConn" connectionString="Data Source=.; Initial Catalog=MyTest; User ID=sa; Password=123456"/>
  </connectionStrings>
</configuration>
           

定義完之後不能忘了添加引用System.Configuration

然後建立SqlHelper類, 在該類中定義對于資料庫的操作

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 省市縣關聯查詢
{
    public static class SqlHelper
    {
        private static string connStr = ConfigurationManager.ConnectionStrings["dbConn"].ConnectionString;

        public static DataTable ExecuteDataSet(string sql, params SqlParameter[] sqlParameters)
        {
            using (SqlConnection conn = new SqlConnection(connStr))
            {
                conn.Open();
                using (SqlCommand cmd = conn.CreateCommand())
                {
                    cmd.Parameters.AddRange(sqlParameters);
                    cmd.CommandText = sql;
                    SqlDataAdapter adapter = new SqlDataAdapter(cmd);
                    DataSet dataSet = new DataSet();
                    adapter.Fill(dataSet);
                    return dataSet.Tables[0];
                }
            }
        }

        public static int ExecuteNonQuery(string sql, params SqlParameter[] sqlParameters)
        {
            using (SqlConnection conn = new SqlConnection(connStr))
            {
                conn.Open();
                using (SqlCommand cmd = conn.CreateCommand())
                {
                    cmd.Parameters.AddRange(sqlParameters);
                    cmd.CommandText = sql;
                    return cmd.ExecuteNonQuery();
                }
            }
        }
    }
}
           

③ 建立主程式

在主程式中需要使用Area類的對象來暫時存儲查詢資訊, 定義如下:

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

namespace 省市縣關聯查詢
{
    public class Area
    {
        public int AreaID { get; set; }
        public string AreaName { get; set; }
    }
}
           

主視窗定義:

<Window x:Name="l" x:Class="省市縣關聯查詢.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="省市縣關聯查詢" Height="350" Width="450" Loaded="l_Loaded">
    <Grid>
        <StackPanel Orientation="Horizontal">
            <ListBox x:Name="ProvName" DisplayMemberPath="AreaName" Width="150" SelectionChanged="ProvName_SelectionChanged"></ListBox>
            <ListBox x:Name="cityName" DisplayMemberPath="AreaName" Width="150" SelectionChanged="cityName_SelectionChanged"></ListBox>
            <ListBox x:Name="countryName" DisplayMemberPath="AreaName" Width="150"></ListBox>
        </StackPanel>
    </Grid>
</Window>
           

給三個ListBox控件賦予Name屬性用于背景調用, DisplayMemberPath用于綁定顯示的值.

背景代碼:

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace 省市縣關聯查詢
{
    /// <summary>
    /// MainWindow.xaml 的互動邏輯
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void l_Loaded(object sender, RoutedEventArgs e)
        {
            List<Area> listProv = new List<Area>();
            //AreaPid 表示該區域直屬的上級區域的 Id, Pid為0表示沒有上級直屬
            DataTable table = SqlHelper.ExecuteDataSet("Select * from AreaFull where AreaPid=0");  
            //foreach (DataRow row in table.Rows)
            //{
            //    Area prov = new Area();
            //    prov.AreaID = (int)row["AreaId"];
            //    prov.AreaName = (string)row["AreaName"];
            //    listProv.Add(prov);
            //}
            //定義一個方法多次使用, 代碼複用
            listProv = TableToList(table);
            ProvName.ItemsSource = listProv;
        }

        private void ProvName_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            List<Area> listCity = new List<Area>();
            Area prov = (Area)ProvName.SelectedItem;
            int provId = prov.AreaID;
            DataTable table = SqlHelper.ExecuteDataSet("Select * from AreaFull where [email protected]",
                new SqlParameter("@provId", provId));
            listCity = TableToList(table);
            cityName.ItemsSource = listCity;
        }


        private void cityName_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            List<Area> listCountry = new List<Area>();
            Area city = (Area)cityName.SelectedItem;

            //當第一級發生改動之後, 引起ProvName_SelectionChanged, 更改掉第二級的資料源
            //這時會引發cityName_SelectionChanged, 并且由于目前的SelectedItem為null,
            //是以如果不判斷的話, 會引起異常.
            if (city != null)
            {
                int cityId = city.AreaID;
                DataTable table = SqlHelper.ExecuteDataSet("Select * from AreaFull where [email protected]",
                   new SqlParameter("@cityId", cityId));
                listCountry = TableToList(table);
                countryName.ItemsSource = listCountry;
            }
            else
                countryName.ItemsSource = null;
        }

        //将傳回的表轉換成List<Area>
        private List<Area> TableToList(DataTable table)
        {
            List<Area> area = new List<Area>();
            foreach (DataRow row in table.Rows)
            {
                Area city = new Area();
                city.AreaID = (int)row["AreaId"];
                city.AreaName = (string)row["AreaName"];
                area.Add(city);
            }
            return area;
        }
    }
}
           

在背景中, 使用List<Area>類型的集合存儲查找傳回的資訊, 然後将控件的ItemsSource綁定到該對象上.

注意:

在進行三級關聯的時候, 需要對第三級進行SelectedItem的判斷.

當第一級發生改動之後, 引起ProvName_SelectionChanged, 更改掉第二級的資料源
這時會引發cityName_SelectionChanged, 并且由于目前的SelectedItem為null,
是以如果不判斷的話, 會引起異常
           

每個用于儲存存儲資訊的集合都不能在外部聲明, 除非使用ObserableList<>

 效果圖:

黑馬程式員 C#學習筆記⑤ 省市縣三級關聯查詢

---------------------- ASP.Net+Unity開發、 .Net教育訓練、期待與您交流! ----------------------詳細請檢視: www.itheima.com