为什么我的多值转换器没有被触发?

Why my multivalue converter is not fired?

我正在尝试使用转换器调整数据网格的列宽。为了进行测试,我有一个 tets 应用程序,它有一个复选框来判断是否使用转换器的值。还有一个文本框,用于说明要应用的宽度。

当我修改复选框或文本框时,会通知视图模型的属性,但不会触发转换器。

我的代码是这样的:

主要windows:

<Window x:Class="ModificarColumnaDataGrid.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:ModificarColumnaDataGrid"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">

    
    <Grid>
        <local:ucControlUsuario HorizontalAlignment="Stretch" Margin="0,0,0,0" VerticalAlignment="Stretch"/>
    </Grid>
</Window>

用户控制:

<UserControl x:Class="ModificarColumnaDataGrid.ucControlUsuario"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:ModificarColumnaDataGrid"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">

    <UserControl.Resources>
        <ResourceDictionary>
            <!--Este diccionario, el GUI, tendrá la configuración general para los diferentes elementos que se tengan en la GUI.-->
            <ResourceDictionary.MergedDictionaries>
                <!--Ruta relativa, porque esta vista está en subdirectorio, al mismo nivel que recursos.-->
                <ResourceDictionary Source="DiccionarioRecursos.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </UserControl.Resources>


    <Grid>
        <CheckBox Content="Use Converter" HorizontalAlignment="Left" Margin="0,10,0,0" VerticalAlignment="Top"
                  IsChecked="{Binding UseConverterIsChecked}"/>
        <TextBox Text="{Binding WidthColumn2, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Left" Margin="106,48,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"/>

        <!--Necesario para poder acceder a las propiedades del datacontext, necesario para los datatriggers.-->
        <FrameworkElement x:Name="ProxyElement" Visibility="Collapsed"/>

        <DataGrid Margin="0,154,0,0" AutoGenerateColumns="false">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Columna1" Width="200"/>
                <DataGridTextColumn Header="Columna2" Width="200">
                    <DataGridTextColumn.ElementStyle>
                        <Style TargetType="{x:Type TextBlock}">
                            <!--<Setter Property="Width" Value="20"/>-->
                            <Setter Property="Width">
                                <Setter.Value>
                                    <MultiBinding Converter="{StaticResource MiMultiValueConverter}" >
                                        <Binding Source="{x:Reference ProxyElement}" Path="DataContext.UseConverterIsChecked" />
                                        <Binding Source="{x:Reference ProxyElement}" Path="DataContext.WidthColumn2" />
                                    </MultiBinding>
                                </Setter.Value>
                            </Setter>
                        </Style>
                    </DataGridTextColumn.ElementStyle>
                </DataGridTextColumn>
                <DataGridTextColumn Header="Columna3" Width="200"/>
            </DataGrid.Columns>
        </DataGrid>
        <Label Content="Pixels column 2" HorizontalAlignment="Left" Margin="0,44,0,0" VerticalAlignment="Top"/>

    </Grid>
</UserControl>

用户控件隐藏代码:

namespace ModificarColumnaDataGrid
{
    /// <summary>
    /// Lógica de interacción para ucControlUsuario.xaml
    /// </summary>
    public partial class ucControlUsuario : UserControl
    {
        public ucControlUsuario()
        {
            InitializeComponent();


            DataContext = new ucControlUsuarioViewModel();
        }
    }
}

用户控件的视图模型:

namespace ModificarColumnaDataGrid
{
    class ucControlUsuarioViewModel : BaseViewModel
    {
        private bool _useConverterIsChecked;

        public bool UseConverterIsChecked
        {
            get { return _useConverterIsChecked; }
            set
            {
                _useConverterIsChecked = value;
                base.RaisePropertyChangedEvent(nameof(UseConverterIsChecked));
            }
        }


        private double _widthColumn2;

        public double WidthColumn2
        {
            get { return _widthColumn2; }
            set
            {
                _widthColumn2 = value;
                base.RaisePropertyChangedEvent(nameof(WidthColumn2));
            }
        }

    }
}

查看模型库:

public 抽象 class BaseViewModel : INotifyPropertyChanging, INotifyPropertyChanged { #region INotifyPropertyChanging 成员

public event PropertyChangingEventHandler PropertyChanging;

#endregion

#region INotifyPropertyChanged Members

public event PropertyChangedEventHandler PropertyChanged;

#endregion

#region Administrative Properties

/// <summary>
/// Whether the view model should ignore property-change events.
/// </summary>
public virtual bool IgnorePropertyChangeEvents { get; set; }

#endregion

#region Public Methods
//@#ESTUDIAR: si esta implemantación es mejor.
//Este método tiene la ventaja de que en el set de la propiedad, con poner OnPropertyChanged() es suficiente, no hace falta
//pasar por parámetro ni el stirng con el nombre de la propiedad ni siquiera la propiedad, porque la coge por defecto.
//Pero se puede pasar la propiedad en caso de que quiera notificar fuera del set, pero no hace falta pasar el string, sino la
//propiedad, por lo que el mantenimiento es mucho mejor.
////////////public void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string paramStrNombrePropiedad = "")
////////////{
////////////    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(paramStrNombrePropiedad));
////////////}


/// <summary>
/// Raises the PropertyChanged event.
/// </summary>
/// <param name="propertyName">The name of the changed property.</param>
public virtual void RaisePropertyChangedEvent(string propertyName)
{
    // Exit if changes ignored
    if (IgnorePropertyChangeEvents) return;

    // Exit if no subscribers
    if (PropertyChanged == null) return;

    // Raise event
    var e = new PropertyChangedEventArgs(propertyName);
    PropertyChanged(this, e);
}

/// <summary>
/// Raises the PropertyChanging event.
/// </summary>
/// <param name="propertyName">The name of the changing property.</param>
public virtual void RaisePropertyChangingEvent(string propertyName)
{
    // Exit if changes ignored
    if (IgnorePropertyChangeEvents) return;

    // Exit if no subscribers
    if (PropertyChanging == null) return;

    // Raise event
    var e = new PropertyChangingEventArgs(propertyName);
    PropertyChanging(this, e);
}

#endregion

}

递归词典:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:conv="clr-namespace:ModificarColumnaDataGrid"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <conv:MiMultiValueConverter x:Key="MiMultiValueConverter" />
</ResourceDictionary>

多值转换器:

namespace ModificarColumnaDataGrid
{
    public class MiMultiValueConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            return 20;
        }


        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

我怎样才能启动转换器?

编辑:

我尝试设置列的宽度而不是样式的文本块:

            <DataGridTextColumn.Width>
                <MultiBinding Converter="{StaticResource MiMultiValueConverter}" >
                                <Binding Source="{StaticResource BindingProxy}" Path="Data.UseConverterIsChecked"/>
                                <Binding Source="{StaticResource BindingProxy}" Path="Data.WidthColumn2" />
                            </MultiBinding>
            </DataGridTextColumn.Width>

但是也不行。

但是,如果我直接在列的宽度 属性 中使用转换器,它会起作用:

<DataGridTextColumn Header="Columna2"
                                    Width="{Binding Data.UseConverterIsChecked, Converter={StaticResource MiValueConverter}, Source={StaticResource BindingProxy}}">

这个解决方案的问题是我需要一个多值转换器,但我不知道如何在列的宽度 属性 中使用它。

谢谢。

The problem with thi solution is that I need a multivalue converter, and I don't know how to use it in the width property of the column.

只需使用对象元素语法设置 Width 属性:

<DataGridTextColumn Header="Columna2">
    <DataGridTextColumn.Width>
        <MultiBinding Converter="{StaticResource MiValueConverter}">
            <Binding Path="Data.UseConverterIsChecked" Source="{StaticResource BindingProxy}" />
    <!-- add more bindings here -->
        </MultiBinding>
    </DataGridTextColumn.Width>
</DataGridTextColumn>