WPF вызывает конвертер значений с пустой строкой - PullRequest
1 голос
/ 13 марта 2020

У меня есть ComboBox, связанный со списком значений, для этого примера простой массив int s. Элемент управления имеет пользовательский ItemTemplate, назначенный для форматирования его элементов, который, в свою очередь, использует IValueConverter для некоторых операций.

В конкретном случае это не удается: если ComboBox имеет Если выбран элемент и список элементов изменяется, конвертер Convert вызывается с пустой строкой, которая, безусловно, не является одним из значений, привязанных к моему элементу управления. (Обратите внимание, что я не говорю о методе ConvertBack.)

Мои вопросы будут:

  1. Почему вызывается IValueConverter с value, являющимся пустой строкой (""), когда ни одна строка никогда не связана с элементом управления?
  2. Каковы некоторые не хакерские решения проблемы? (Я мог бы просто поместить if (value is "") return null; в преобразователь, и, похоже, ошибка go исчезла, но я чувствую, что лечит симптомы, а не причину.)

Проблема может быть воспроизведена с помощью простого проекта WPF (dotnet new wpf), содержащего только эти 3 файла (проблема присутствует как в версиях Framework, так и в Core. NET):

MainWindow.xaml:

<Window x:Class="test.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:test"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <ComboBox x:Name="Selector" VerticalAlignment="Center" HorizontalAlignment="Center" Width="100">
            <ComboBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Converter={x:Static local:Converter.Instance}}" />
                </DataTemplate>
            </ComboBox.ItemTemplate>
        </ComboBox>
        <Button HorizontalAlignment="Right" VerticalAlignment="Bottom" Content="Replace" Click="Button_Click" />
    </Grid>
</Window>

MainWindow.xaml.cs:

using System;
using System.Windows;

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

            Selector.ItemsSource = new int[] { 1, 2, 3 };
        }

      private void Button_Click(object sender, RoutedEventArgs e)
      {
         Selector.ItemsSource = new int[] { -1, -2, -3 };
      }

      [STAThread]
      public static void Main(String[] args)
      {
         new MainWindow().ShowDialog();
      }
   }
}

И, наконец, Converter.cs:

using System;
using System.Diagnostics;
using System.Globalization;
using System.Windows.Data;

namespace test
{
    class Converter : IValueConverter
    {
        public static Converter Instance { get; } = new Converter();

        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            Debug.Assert(value is int);

            return (2 * (int) value).ToString();
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotSupportedException();
        }
    }
}

Эти 3 файла представляют собой минимальный пример, демонстрирующий такое поведение. Если нажать кнопку «заменить» без выбора чего-либо из ComboBox, программа работает нормально. Однако, если какое-либо значение выбрано в ComboBox до нажатия кнопки, утверждение в преобразователе не выполняется, поскольку при нажатии кнопки преобразователю передается значение value из "".

1 Ответ

1 голос
/ 13 марта 2020

Я попробовал ваш код, когда текущий выбранный элемент не находится в источнике вновь установленного элемента, выбранный элемент должен быть изменен, верно? Таким образом, они изменяют выбранный элемент на "". Это выбранный элемент, который вы видите в исходном состоянии запущенного приложения.

Фактически, если вы сохраните выбранный элемент в новом источнике элементов, он не выполнит преобразование со значением "". Предположим, что ваш первоначальный источник предмета -

Selector.ItemsSource = new int[] { 1, 2, 3 };

. Теперь вы выбираете второй элемент, который отображается как 4 в вашем поле со списком, и нажимаете замену, чтобы запустить его.

 Selector.ItemsSource = new int[]{ -1, 2, -3 };

Тогда он выиграл ' t выполнить конвертер со значением "".

Здесь проблема в том, что выбранный элемент отсутствует в новом источнике элементов, поэтому Combobox выбирает значение по умолчанию, и ваш Combobox будет вести себя так же, как вы начали применение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...