_9WPF绑定元素和绑定模式

This commit is contained in:
Bunny 2025-01-25 23:16:24 +08:00
parent d9e7427fc8
commit a42b15fd1c
9 changed files with 425 additions and 1 deletions

View File

@ -551,4 +551,301 @@ private void Window_Closed(object sender, EventArgs e)
> - **`OnLoaded`**:窗口完全加载并显示后调用。
> - **`Activated`**:窗口获得焦点并被激活时触发。
> - **`OnClosing`**:窗口即将关闭时调用。
> - **`OnClosed`**:窗口完全关闭后调用。
> - **`OnClosed`**:窗口完全关闭后调用。
## WPF绑定模式
在 WPFWindows Presentation Foundation**数据绑定**Data Binding是一项核心功能它允许将用户界面UI控件与数据源之间建立连接从而使得 UI 和数据之间能够自动同步。WPF 提供了多种**绑定模式**Binding Modes每种模式都有其特定的行为和用途用于处理数据从视图到视图模型或模型的更新、同步等。
### WPF 中的绑定模式
WPF 支持四种主要的绑定模式Binding Modes
1. **OneWay单向绑定**
2. **TwoWay双向绑定**
3. **OneWayToSource单向绑定到源**
4. **OneTime一次性绑定**
#### 1. **OneWay单向绑定**
**定义**:单向绑定模式将数据源的变化反映到 UI 元素中即数据从数据源到视图UI。数据从源控件如模型、视图模型流向目标控件如文本框、标签等
**特点**
- 数据流动方向是从数据源到目标控件。
- UI 元素的变化不会影响数据源。
- 常用于显示数据,不需要用户交互修改数据。
**示例**:绑定一个 `Label``Content` 属性到一个模型的属性。
```xml
<TextBlock Text="{Binding Path=Name}" />
public class Person
{
public string Name { get; set; }
}
// 在视图模型中绑定:
public class MainViewModel
{
public Person Person { get; set; } = new Person { Name = "John Doe" };
}
```
#### 2. **TwoWay双向绑定**
**定义**:双向绑定允许数据在两个方向流动,既可以从源到目标,也可以从目标到源。当用户更改 UI 元素的值时数据源会自动更新同样当数据源发生变化时UI 元素会同步更新。
**特点**
- 数据流动是双向的(源 -> 目标 和 目标 -> 源)。
- 常用于用户输入的场景,如文本框输入、下拉框选择等。
- 适用于需要用户交互且 UI 需要实时反映的数据。
**示例**:绑定一个 `TextBox``Text` 属性到视图模型中的属性。
```xml
<TextBox Text="{Binding Path=Name, Mode=TwoWay}" />
public class Person
{
public string Name { get; set; }
}
// 在视图模型中绑定:
public class MainViewModel
{
public Person Person { get; set; } = new Person { Name = "John Doe" };
}
```
如果用户在 `TextBox` 中输入内容,`Person.Name` 会自动更新为输入的值。
#### 3. **OneWayToSource单向绑定到源**
**定义**:这种绑定模式与 `OneWay` 类似,但数据流动的方向相反。它将 UI 元素的变化反映到数据源,即从目标控件(如文本框、按钮等)到数据源。
**特点**
- 数据流动方向是从目标到数据源。
- 适用于一些需要监听 UI 元素变化并更新数据源的场景,但不要求数据源的变化影响到 UI 元素。
- 一般用于用户输入的情况,数据源的更改不需要直接反映到 UI 上。
**示例**:将 `TextBox``Text` 属性绑定到数据源,并将用户输入的值更新到数据源中。
```xml
<TextBox Text="{Binding Path=Name, Mode=OneWayToSource}" />
public class Person
{
public string Name { get; set; }
}
// 在视图模型中绑定:
public class MainViewModel
{
public Person Person { get; set; } = new Person { Name = "John Doe" };
}
```
当用户在 `TextBox` 中输入内容时,`Person.Name` 会自动更新,但不会反过来更新 `TextBox`
#### 4. **OneTime一次性绑定**
**定义**:一次性绑定模式将数据源的值传递给目标控件,但不会再进行同步更新。数据只在初始时绑定一次,之后不会跟随数据源的变化而更新。
**特点**
- 数据仅在第一次绑定时传递到目标控件。
- 适用于不需要随数据源变化自动更新 UI 的场景。
- 适用于静态数据,如初始化时显示的值。
**示例**:在应用启动时绑定初始数据。
```xml
<TextBlock Text="{Binding Path=Name, Mode=OneTime}" />
public class Person
{
public string Name { get; set; }
}
// 在视图模型中绑定:
public class MainViewModel
{
public Person Person { get; set; } = new Person { Name = "John Doe" };
}
```
`TextBlock``Text` 属性会在应用启动时绑定一次,但在之后的任何数据变化都不会反映到 UI 上。
### 选择合适的绑定模式
选择绑定模式时需要根据实际需求来决定。以下是不同情况适用的模式:
1. **`OneWay`**
- 用于显示数据UI 不需要编辑或修改数据。
- 适用于只读的文本展示等场景。
2. **`TwoWay`**
- 用于需要用户输入并与数据源实时同步的场景。
- 适用于输入框、下拉框等用户可编辑控件。
3. **`OneWayToSource`**
- 用于需要监听 UI 元素的变化并更新数据源的场景,且不需要将数据源的变化反映回 UI。
- 适用于需要提交用户输入但不需要实时更新 UI 的场景。
4. **`OneTime`**
- 用于初始化数据,仅绑定一次,之后不再更新。
- 适用于静态数据或加载一次后不再变化的场景。
### 绑定模式的代码示例
以下是完整的 `TwoWay` 绑定的代码示例:
```xml
<Window x:Class="WpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Binding Example" Height="200" Width="300">
<Grid>
<TextBox Text="{Binding Name, Mode=TwoWay}" VerticalAlignment="Center" HorizontalAlignment="Center" Width="200" />
</Grid>
</Window>
public class MainWindowViewModel
{
public string Name { get; set; } = "John Doe";
}
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new MainWindowViewModel();
}
}
```
在这个示例中,`TextBox` 的 `Text` 属性绑定到了视图模型中的 `Name` 属性,且使用 `TwoWay` 模式,意味着如果用户修改 `TextBox` 中的内容,`Name` 属性会实时更新,反之,`Name` 的变化会反映在 `TextBox` 中。
在 WPF 中,**多绑定**Multiple Bindings是指将一个目标控件的属性绑定到多个数据源上或使用多个绑定来决定控件的显示内容。通常情况下我们可以使用 `MultiBinding``IMultiValueConverter` 来实现多绑定。
### **基础多绑定示例**
`MultiBinding` 允许你将多个数据源绑定到一个目标控件上,并通过一个 `IMultiValueConverter` 将多个数据源的值转换为一个值,从而决定目标控件的最终显示。
假设我们有两个文本框,用户分别输入名字和姓氏,我们想在一个 `TextBlock` 中显示完整的姓名。我们可以使用 `MultiBinding` 来实现。
#### XAML 示例:
```xml
<Window x:Class="WpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApp"
Title="MultiBinding Example" Height="200" Width="300">
<Window.Resources>
<!-- 定义一个 MultiValueConverter 用于合并名字和姓氏 -->
<local:FullNameConverter x:Key="FullNameConverter" />
</Window.Resources>
<Grid>
<TextBox x:Name="FirstNameTextBox" HorizontalAlignment="Center" VerticalAlignment="Top" Width="200" Margin="0,20,0,0" />
<TextBox x:Name="LastNameTextBox" HorizontalAlignment="Center" VerticalAlignment="Top" Width="200" Margin="0,60,0,0" />
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Top" Margin="0,100,0,0">
<!-- 使用 MultiBinding 来绑定两个 TextBox 的值 -->
<TextBlock.Text>
<MultiBinding Converter="{StaticResource FullNameConverter}">
<Binding Path="Text" ElementName="FirstNameTextBox"/>
<Binding Path="Text" ElementName="LastNameTextBox"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</Grid>
</Window>
```
> 1. `MultiBinding` 允许你将多个绑定连接到同一个目标控件(这里是 `TextBlock.Text`)。
> 2. 绑定的源控件是 `FirstNameTextBox``LastNameTextBox`
> 3. 使用 `IMultiValueConverter`(在这个例子中是 `FullNameConverter`)将多个绑定的值(名字和姓氏)转换为一个最终值并显示在 `TextBlock` 中。
### `MultiBinding` 进阶
`MultiBinding` 可以用于处理更复杂的场景,比如通过多个条件来决定控件的属性值。例如,依据多个条件显示不同的文本或颜色。
#### XAML 示例:
```xml
<Window x:Class="WpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApp"
Title="MultiBinding Example" Height="200" Width="300">
<Window.Resources>
<!-- 定义一个 MultiValueConverter 用于根据多个条件选择文本颜色 -->
<local:TextColorConverter x:Key="TextColorConverter" />
</Window.Resources>
<Grid>
<CheckBox x:Name="IsActiveCheckBox" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="20,20,0,0" Content="Is Active?" />
<CheckBox x:Name="HasPermissionCheckBox" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="20,60,0,0" Content="Has Permission?" />
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Top" Margin="0,100,0,0" FontSize="16">
<!-- 使用 MultiBinding 和 Converter 设置 TextBlock 的颜色 -->
<TextBlock.Foreground>
<MultiBinding Converter="{StaticResource TextColorConverter}">
<Binding Path="IsChecked" ElementName="IsActiveCheckBox" />
<Binding Path="IsChecked" ElementName="HasPermissionCheckBox" />
</MultiBinding>
</TextBlock.Foreground>
Text Block Color Based on Conditions
</TextBlock>
</Grid>
</Window>
```
#### `TextColorConverter` 实现:
```csharp
using System;
using System.Globalization;
using System.Windows.Data;
using System.Windows.Media;
namespace WpfApp
{
public class TextColorConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
bool isActive = (bool)(values[0] ?? false);
bool hasPermission = (bool)(values[1] ?? false);
if (isActive && hasPermission)
{
return new SolidColorBrush(Colors.Green); // 如果两个条件都满足,显示绿色
}
return new SolidColorBrush(Colors.Red); // 否则显示红色
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
return null; // 不需要双向绑定
}
}
}
```
> - 在这个例子中,`TextBlock.Foreground` 属性的颜色依赖于两个复选框的状态(`IsActiveCheckBox` 和 `HasPermissionCheckBox`)。
>
> - ```
> TextColorConverter
> ```
>
> 判断两个条件:
>
> - 如果两个复选框都被选中,`TextBlock` 的颜色是绿色。
> - 否则,颜色为红色。
>
> 1. **绑定多个属性**:通过 `MultiBinding` 可以同时绑定多个数据源到一个目标控件的属性。在数据源变化时,`IMultiValueConverter` 将负责处理多个源的逻辑,返回最终的结果。
> 2. **双向绑定**:虽然 `MultiBinding` 主要用于单向绑定UI -> 数据源),如果需要双向绑定,可以通过设置 `Mode=TwoWay` 来实现。但一般来说,`MultiBinding` 多用于显示和数据转换,而不是双向交互。
> 3. **性能**:在进行多绑定时,尤其是复杂的转换时,需要注意性能影响。如果绑定源的数量或更新频率较高,可能会影响应用的性能。

View File

@ -16,6 +16,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "_7鼠标状态移动监视"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "_8鼠标拖拽", "_8鼠标拖拽\_8鼠标拖拽.csproj", "{2B87A81A-A1B0-4243-92BD-1281097B79E2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "_9WPF绑定元素和绑定模式", "_9WPF绑定元素和绑定模式\_9WPF绑定元素和绑定模式.csproj", "{20E3BF0D-57DC-4BA5-8FB2-A06DC15008AF}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -54,5 +56,9 @@ Global
{2B87A81A-A1B0-4243-92BD-1281097B79E2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2B87A81A-A1B0-4243-92BD-1281097B79E2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2B87A81A-A1B0-4243-92BD-1281097B79E2}.Release|Any CPU.Build.0 = Release|Any CPU
{20E3BF0D-57DC-4BA5-8FB2-A06DC15008AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{20E3BF0D-57DC-4BA5-8FB2-A06DC15008AF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{20E3BF0D-57DC-4BA5-8FB2-A06DC15008AF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{20E3BF0D-57DC-4BA5-8FB2-A06DC15008AF}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,9 @@
<Application x:Class="_WPF绑定元素和绑定模式.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:_WPF绑定元素和绑定模式"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>

View File

@ -0,0 +1,12 @@
using System.Configuration;
using System.Data;
using System.Windows;
namespace _WPF绑定元素和绑定模式;
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
}

View File

@ -0,0 +1,10 @@
using System.Windows;
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]

View File

@ -0,0 +1,27 @@
<Window x:Class="_WPF绑定元素和绑定模式.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"
mc:Ignorable="d"
Icon="public/logo.png" Title="_9WPF绑定元素和绑定模式" Height="450" Width="800">
<StackPanel>
<Slider Name="SliderFontSize" Minimum="1" Maximum="100" Value="40" TickFrequency="1" TickPlacement="TopLeft" />
<Label>
Binding 绑定元素 ElementName=SliderFontSize 指定元素名称,Path=Value 指定绑定的值
</Label>
<TextBlock Margin="10" Text="简单的文字" Name="TextBlockShow" />
<WrapPanel>
<Button Margin="5 0" Padding="15 5" Name="SetSmall" Click="SetSmall_OnClick">设置小号</Button>
<Button Margin="5 0" Padding="15 5" Name="SetNormal" Click="SetNormal_OnClick">设置默认</Button>
<Button Margin="5 0" Padding="15 5" Name="SetLarge" Click="SetLarge_OnClick">设置大号</Button>
<Label>不要直接设置在字体上会使用字面绑定代替元素绑定或者使用Mode为TwoWay</Label>
</WrapPanel>
<WrapPanel>
<Button Margin="5 0" Padding="15 5" Name="ClearBinding" Click="ClearBinding_OnClick">清除绑定</Button>
</WrapPanel>
</StackPanel>
</Window>

View File

@ -0,0 +1,45 @@
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
namespace _WPF绑定元素和绑定模式;
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Console.WriteLine("使用代码模式的绑定");
var binding = new Binding
{
Source = SliderFontSize,
Path = new PropertyPath("Value"),
Mode = BindingMode.TwoWay
};
TextBlockShow.SetBinding(TextBlock.FontSizeProperty, binding);
}
private void SetLarge_OnClick(object sender, RoutedEventArgs e)
{
SliderFontSize.Value = 100;
}
private void SetNormal_OnClick(object sender, RoutedEventArgs e)
{
SliderFontSize.Value = 40;
}
private void SetSmall_OnClick(object sender, RoutedEventArgs e)
{
SliderFontSize.Value = 10;
}
private void ClearBinding_OnClick(object sender, RoutedEventArgs e)
{
BindingOperations.ClearAllBindings(TextBlockShow);
}
}

View File

@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UseWPF>true</UseWPF>
<RootNamespace>_WPF绑定元素和绑定模式</RootNamespace>
</PropertyGroup>
<ItemGroup>
<Resource Include="public\logo.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Resource>
</ItemGroup>
</Project>

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB