Каков жизненный цикл конвертера? - PullRequest
4 голосов
/ 10 июля 2019

Каков жизненный цикл конвертера?
Когда вы создаете преобразователь, полученный из IValueConverter и IMultiValueConverter, класс не является статическим, равно как и функции Convert() и ConvertBack(). Так каков жизненный цикл этого экземпляра класса?
Если я использую конвертер в XAML в нескольких привязках, создается ли новый экземпляр класса для каждого элемента управления? Или новый экземпляр класса создается каждый раз при обновлении привязки? Или, может быть, существует только один экземпляр для всего приложения?

Ответы [ 2 ]

2 голосов
/ 10 июля 2019

Жизненный цикл конвертера в целом такой же, как у любого экземпляра объекта 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 будет другим. Вы можете назначить экземпляры объекта свойству, как описано выше, в качестве ресурса. Но вместо этого вы можете использовать Синтаксис элемента свойства , чтобы создать экземпляр объекта XAML:

<Binding Path="Values">
    <Binding.Converter>
        <BooleanToVisibilityConverter />
    </Binding.Converter>
</Binding>

Это объявление приводит к экземпляру конвертера, который используется только для этой конкретной привязки (или свойства). Это объявление не ссылается на ресурс (используя StaticResource или DynamicResource), но явно создает экземпляр, который назначается исключительно свойству (в данном случае Binding.Converter).

В качестве примечания:
StaticResource не означает, что ресурс является статическим. Это расширение разметки, которое инструктирует синтаксическому анализатору XAML искать дерево ресурсов, чтобы найти предопределенный экземпляр. То же самое DynamicResource. Единственное отличие состоит в том, что StaticResource указывает синтаксическому анализатору XAML разрешить ссылку на ресурс во время компиляции, тогда как DynamicResource позволяет анализатору XAML создать вместо этого выражение, которое будет оцениваться во время выполнения. DynamicResource поэтому разрешает ресурс во время выполнения.

0 голосов
/ 10 июля 2019

Номер экземпляра конвертера зависит от вашего кода. Вы можете попробовать этот код самостоятельно:

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;
        }
    }
}

Результат изображения, как показано ниже: enter image description here

...