_9WPF绑定元素和绑定模式
This commit is contained in:
parent
d9e7427fc8
commit
a42b15fd1c
297
README/重要说明.md
297
README/重要说明.md
|
@ -552,3 +552,300 @@ private void Window_Closed(object sender, EventArgs e)
|
|||
> - **`Activated`**:窗口获得焦点并被激活时触发。
|
||||
> - **`OnClosing`**:窗口即将关闭时调用。
|
||||
> - **`OnClosed`**:窗口完全关闭后调用。
|
||||
|
||||
## WPF绑定模式
|
||||
|
||||
在 WPF(Windows 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. **性能**:在进行多绑定时,尤其是复杂的转换时,需要注意性能影响。如果绑定源的数量或更新频率较高,可能会影响应用的性能。
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
|
@ -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
|
||||
{
|
||||
}
|
|
@ -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)
|
||||
)]
|
|
@ -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>
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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 |
Loading…
Reference in New Issue