iT邦幫忙

2025 iThome 鐵人賽

DAY 17
0

昨天我們學了 Binding 的基本模式,今天要更深入:

  • DataContext 的設定方式
  • View First 與 ViewModel First 的差異
  • ObservableCollection 的應用

DataContext 設定方式

在 WPF 中,Binding 必須知道資料來源是哪個物件,而這個來源就是 DataContext

有幾種設定方式:


1) 後端程式碼指定 (Code-behind)

最常見的方式是在 MainWindow.xaml.cs 設定:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        this.DataContext = new StockViewModel
        {
            StockName = "2330 台積電",
            Price = 1265m
        };
    }
}

這樣 MainWindow 底下的所有控制項就能直接綁定到 StockViewModel 的屬性。


2) XAML 靜態指定

有時候我們希望直接在 XAML 中設定 DataContext

<Window x:Class="MyStockApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:vm="clr-namespace:MyStockApp.ViewModels"
        Title="股票工具" Height="300" Width="400">

    <Window.DataContext>
        <vm:StockViewModel StockName="2303 聯電" Price="45.7" />
    </Window.DataContext>

    <StackPanel>
        <TextBlock Text="{Binding StockName}" FontSize="16"/>
        <TextBlock Text="{Binding Price}" FontSize="16"/>
    </StackPanel>
</Window>

3) 控制項單獨設定

你也可以只針對某個控制項單獨設定 DataContext

<StackPanel>
    <TextBlock Text="{Binding StockName}" />
    <StackPanel.DataContext>
        <vm:StockViewModel StockName="2317 鴻海" Price="103" />
    </StackPanel.DataContext>
    <TextBlock Text="{Binding Price}" />
</StackPanel>

這種方式只會影響 StackPanel 裡的元素,不會影響整個 Window


View First 與 ViewModel First

在 MVVM 架構中,會有兩種設計流程:

1) View First

  • 先建立 View (XAML)
  • 再在後端指定它的 DataContext
var window = new MainWindow();
window.DataContext = new StockViewModel();
window.Show();

優點:直覺、快速,適合小專案。
缺點:View 會依賴程式碼建立 ViewModel,耦合度稍高。


2) ViewModel First

  • 先建立 ViewModel
  • 再用程式或 DI 容器找到對應的 View,並把 ViewModel 傳入
var vm = new StockViewModel();
var window = new MainWindow { DataContext = vm };
window.Show();

優點:更符合「View 與 ViewModel 分離」的精神,可以搭配 DI 容器(如 DryIoc、Autofac)。
缺點:初學時需要額外理解 IoC/DI。


ObservableCollection

在前面介紹 Binding 時,我們都是處理單一屬性。
但是在選股工具裡,股票清單會有很多筆資料,這時就要用 集合 (Collection)。

如果我們用 List,問題是:

加入或刪除元素時,UI 不會自動更新

解決方案是 ObservableCollection。

例子:使用 ObservableCollection
假設我們有一個 ViewModel 管理多檔股票:

using System.Collections.ObjectModel;

public class StockListViewModel
{
    public ObservableCollection<StockViewModel> Stocks { get; set; }

    public StockListViewModel()
    {
        Stocks = new ObservableCollection<StockViewModel>
        {
            new StockViewModel { StockName = "2330 台積電", Price = 1265m },
            new StockViewModel { StockName = "2303 聯電", Price = 45.7m },
            new StockViewModel { StockName = "2317 鴻海", Price = 103m }
        };
    }
}

XAML:

<ListBox ItemsSource="{Binding Stocks}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding StockName}" Width="120"/>
                <TextBlock Text="{Binding Price}" Width="80"/>
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

後端:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = new StockListViewModel();
    }
}

效果:

  • 初始時會顯示三檔股票

  • 如果在程式中 Stocks.Add(new StockViewModel { StockName = "2881 富邦金", Price = 63.2m });
    → UI 會自動多一筆「2881 富邦金」

  • 如果用 Stocks.RemoveAt(0);
    → UI 會自動移除第一筆資料

為什麼不是用 List?

因為 ObservableCollection 會在元素增刪時發出通知,WPF UI 會自動刷新。使用List要自行處理UI更新的通知,雖然也是可行但稍微麻煩。


小結

今天我們學會了:

  • DataContext 的設定方式(後端程式、XAML 靜態、單獨控制項)
  • View First 與 ViewModel First 的差異
  • ObservableCollection:集合資料能自動通知 UI 更新

上一篇
Day 16 - WPF 資料綁定 (Binding) 基礎
下一篇
Day 18 - WPF Trigger介紹
系列文
30天快速上手製作WPF選股工具 — 從C#基礎到LiteDB與Web API整合21
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言