转换器的生命周期是多少?
What is the lifecycle of a converter?
转换器的生命周期是多少?
当您创建从 IValueConverter
和 IMultiValueConverter
派生的转换器时,class 不是静态的,Convert()
和 ConvertBack()
函数也不是。那么 class 实例的生命周期是多少?
如果我在多个 Binding 中使用 XAML 中的转换器,是否为每个控件创建了 class 的新实例?还是每次更新 Binding 时都会创建 class 的新实例?或者整个应用程序可能只有一个实例?
converter的实例数取决于你的code.You可以自己试试这个代码:
Xaml
<Window x:Class="ConverterTest.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:ConverterTest"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<local:ToStringConverter x:Key="StaticToStringConverter"/>
</Window.Resources>
<StackPanel>
<Slider x:Name="Slider"/>
<TextBlock Text="{Binding ElementName=Slider,Path=Value,Converter={local:ToStringConverter}}"/>
<TextBlock Text="{Binding ElementName=Slider,Path=Value,Converter={local:ToStringConverter}}"/>
<TextBlock Text="{Binding ElementName=Slider,Path=Value,Converter={StaticResource StaticToStringConverter}}"/>
<TextBlock Text="{Binding ElementName=Slider,Path=Value,Converter={StaticResource StaticToStringConverter}}"/>
</StackPanel>
xaml.cs
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
using System.Windows.Markup;
namespace ConverterTest
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
sealed class ToStringConverter : MarkupExtension, IValueConverter
{
Guid guid = Guid.NewGuid();
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
Console.WriteLine(guid);
return $"{guid.ToString()}:{value.ToString()}";
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
private ToStringConverter _converter;
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (_converter == null)
{
_converter = new ToStringConverter();
}
return _converter;
}
}
}
结果图如下:
转换器的生命周期通常与任何 XAML 对象实例相同,并且取决于声明。通常转换器被声明为 ResourceDictionary
:
的资源
<Window.Resources>
<BooleanToVisibilityConverterx:Key="BooleanToVisibilityConverter" />
</Window.Resources>
在这种情况下,转换器(或一般的资源)被重复用于对它的每个引用。这是因为 x:Shared
属性。该属性默认为 true
,它指示 XAML 解析器重用对象的实例。您可以将其明确设置为 false
:
<Window.Resources>
<BooleanToVisibilityConverterx:Key="BooleanToVisibilityConverter" x:Shared="False" />
</Window.Resources>
现在每次引用资源时,XAML 解析器都会创建一个新实例。
如果在 ResourceDictionary
之外声明对象,XAML 解析器的行为是不同的。您可以像上面那样将对象实例作为资源分配给 属性。但是您也可以使用 Property Element Syntax 来实例化一个 XAML 对象:
<Binding Path="Values">
<Binding.Converter>
<BooleanToVisibilityConverter />
</Binding.Converter>
</Binding>
此声明生成转换器实例,仅用于此特定绑定(或 属性)。此声明不引用资源(使用 StaticResource
or DynamicResource
)但显式创建一个专门分配给 属性 的实例(在本例中为 Binding.Converter
)。
旁注:
StaticResource
does not mean that the resource is static. It's a markup extension that instructs the XAML parser to lookup the resource tree to find a predefined instance. Same does DynamicResource
。唯一的区别是 StaticResource
指示 XAML 解析器在编译时解析对资源的引用,而 DynamicResource
让 XAML 解析器创建一个表达式,它将在 运行 时间进行评估。 DynamicResource
因此在 运行 时解析资源。
转换器的生命周期是多少?
当您创建从 IValueConverter
和 IMultiValueConverter
派生的转换器时,class 不是静态的,Convert()
和 ConvertBack()
函数也不是。那么 class 实例的生命周期是多少?
如果我在多个 Binding 中使用 XAML 中的转换器,是否为每个控件创建了 class 的新实例?还是每次更新 Binding 时都会创建 class 的新实例?或者整个应用程序可能只有一个实例?
converter的实例数取决于你的code.You可以自己试试这个代码:
Xaml
<Window x:Class="ConverterTest.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:ConverterTest"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<local:ToStringConverter x:Key="StaticToStringConverter"/>
</Window.Resources>
<StackPanel>
<Slider x:Name="Slider"/>
<TextBlock Text="{Binding ElementName=Slider,Path=Value,Converter={local:ToStringConverter}}"/>
<TextBlock Text="{Binding ElementName=Slider,Path=Value,Converter={local:ToStringConverter}}"/>
<TextBlock Text="{Binding ElementName=Slider,Path=Value,Converter={StaticResource StaticToStringConverter}}"/>
<TextBlock Text="{Binding ElementName=Slider,Path=Value,Converter={StaticResource StaticToStringConverter}}"/>
</StackPanel>
xaml.cs
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
using System.Windows.Markup;
namespace ConverterTest
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
sealed class ToStringConverter : MarkupExtension, IValueConverter
{
Guid guid = Guid.NewGuid();
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
Console.WriteLine(guid);
return $"{guid.ToString()}:{value.ToString()}";
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
private ToStringConverter _converter;
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (_converter == null)
{
_converter = new ToStringConverter();
}
return _converter;
}
}
}
结果图如下:
转换器的生命周期通常与任何 XAML 对象实例相同,并且取决于声明。通常转换器被声明为 ResourceDictionary
:
<Window.Resources>
<BooleanToVisibilityConverterx:Key="BooleanToVisibilityConverter" />
</Window.Resources>
在这种情况下,转换器(或一般的资源)被重复用于对它的每个引用。这是因为 x:Shared
属性。该属性默认为 true
,它指示 XAML 解析器重用对象的实例。您可以将其明确设置为 false
:
<Window.Resources>
<BooleanToVisibilityConverterx:Key="BooleanToVisibilityConverter" x:Shared="False" />
</Window.Resources>
现在每次引用资源时,XAML 解析器都会创建一个新实例。
如果在 ResourceDictionary
之外声明对象,XAML 解析器的行为是不同的。您可以像上面那样将对象实例作为资源分配给 属性。但是您也可以使用 Property Element Syntax 来实例化一个 XAML 对象:
<Binding Path="Values">
<Binding.Converter>
<BooleanToVisibilityConverter />
</Binding.Converter>
</Binding>
此声明生成转换器实例,仅用于此特定绑定(或 属性)。此声明不引用资源(使用 StaticResource
or DynamicResource
)但显式创建一个专门分配给 属性 的实例(在本例中为 Binding.Converter
)。
旁注:
StaticResource
does not mean that the resource is static. It's a markup extension that instructs the XAML parser to lookup the resource tree to find a predefined instance. Same does DynamicResource
。唯一的区别是 StaticResource
指示 XAML 解析器在编译时解析对资源的引用,而 DynamicResource
让 XAML 解析器创建一个表达式,它将在 运行 时间进行评估。 DynamicResource
因此在 运行 时解析资源。