You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

解决.NET Framework4.8 WPF中IsAsync绑定与MahApps全选冲突

问题:WPF DataGrid异步绑定与MahApps CellEditAssist全选功能冲突

在基于.NET Framework 4.8的WPF应用中,为优化DataGrid性能给列绑定设置IsAsync=true,但该设置与MahApps的mah:DataGridHelper.EnableCellEditAssist="True"功能冲突:编辑单元格时,先显示选中的回退值,异步加载绑定值后光标跳至文本开头,无法保持正常全选状态;仅当IsAsync=false时全选功能正常。

临时解决方案

找到一种可行的临时解决办法:借助Binding的NotifyOnTargetUpdated属性(需设为true),通过自定义附加属性监听TargetUpdated事件,在绑定值更新后重新聚焦并全选文本。

原冲突场景代码

XAML布局

<UserControl
 ...
 xmlns:mah="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
 ...
>
...
<DataGrid
    CanUserDeleteRows="False"
    Panel.ZIndex="0"
    ScrollViewer.IsDeferredScrollingEnabled="False"
    Visibility="{Binding ShowSalesLines, Converter={StaticResource BooleanToVisibilityConverter}}"
    Grid.Column="0"
    ItemsSource="{Binding CurrentSalesLines, IsAsync=True, UpdateSourceTrigger=PropertyChanged}"
    x:Name="SalesLinesDatagrid"
    SelectionMode="Extended"
    PreviewKeyDown="SalesLinesDatagrid_PreviewKeyDown"
    VirtualizingPanel.IsVirtualizingWhenGrouping="True"
    EnableRowVirtualization="True"
    VirtualizingPanel.IsVirtualizing="True"
    EnableColumnVirtualization="True"
    CanUserAddRows="False"
    AutoGenerateColumns="False"
    SelectedItem="{Binding CurrentSaleLine, Mode=TwoWay}"
    Style="{StaticResource MahApps.Styles.DataGrid.Azure}"
    OverridesDefaultStyle="False"
    Margin="10"
    IsReadOnly="false"
    CanUserReorderColumns="False"
    CanUserResizeRows="False"
    CanUserSortColumns="False"
    VirtualizingPanel.IsContainerVirtualizable="True"
    VirtualizingPanel.VirtualizationMode="Recycling"
    VirtualizingPanel.ScrollUnit="Pixel"
    SnapsToDevicePixels="True"
    VirtualizingPanel.CacheLengthUnit="Pixel"
    ScrollViewer.PanningDeceleration="5"
    >
<DataGrid.Columns>
<DataGridTextColumn
    VirtualizingPanel.VirtualizationMode="Recycling"
    VirtualizingPanel.IsContainerVirtualizable="True"
    VirtualizingPanel.IsVirtualizing="True"
    Header="Prec. Unit."
    Width="auto"
    VirtualizingPanel.ScrollUnit="Pixel"
    MinWidth="75"
    mah:DataGridHelper.EnableCellEditAssist="True"
    EditingElementStyle="{StaticResource DataGridTextEditingStyle}"
    ElementStyle="{StaticResource DataGridTextColumnHorizontalRight}"
    Binding="{Binding SALESPRICE, StringFormat='0.000', ConverterCulture=es-ES, UpdateSourceTrigger=LostFocus, IsAsync=True, Mode=TwoWay, ValidatesOnDataErrors=True, FallbackValue='0'}"
    />
    </DataGrid.Columns>
</DataGrid>
...
</UserControl>

样式定义

<Style
    x:Key="DataGridTextColumnHorizontalRight"
    TargetType="TextBlock"
    >
    <Setter
        Property="HorizontalAlignment"
        Value="Right"
        />
</Style>

<Style
        x:Key="DataGridTextEditingStyle"
        TargetType="TextBox"
        BasedOn="{StaticResource MahApps.Styles.TextBox.DataGrid.Editing}"
        >
        <Setter
            Property="mah:DataGridHelper.EnableCellEditAssist"
            Value="True"
            />
        <Setter
            Property="mah:TextBoxHelper.ClearTextButton"
            Value="False"
            />
</Style>

ViewModel属性

private decimal _salesPrice;
[Column(TypeName = "numeric")]
public decimal SALESPRICE
{
    get
    {
        return _salesPrice;
    }
    set
    {
        SetProperty(ref _salesPrice, Math.Round(value, 3, MidpointRounding.AwayFromZero));
        OnPropertyChanged(new PropertyChangedEventArgs(nameof(LINEAMOUNT)));
    }
}

修复方案代码

自定义附加属性辅助类

public static class TextBoxBehavior
{
    public static readonly DependencyProperty SelectAllOnGotFocusProperty =
        DependencyProperty.RegisterAttached(
            "SelectAllOnGotFocus",
            typeof(bool),
            typeof(TextBoxBehavior),
            new UIPropertyMetadata(false, OnSelectAllOnGotFocusChanged));

    public static bool GetSelectAllOnGotFocus(DependencyObject obj)
    {
        return (bool)obj.GetValue(SelectAllOnGotFocusProperty);
    }

    public static void SetSelectAllOnGotFocus(DependencyObject obj, bool value)
    {
        obj.SetValue(SelectAllOnGotFocusProperty, value);
    }

    private static void OnSelectAllOnGotFocusChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (d is TextBox textBox)
        {
            if ((bool)e.NewValue)
            {
                textBox.GotFocus += TextBox_GotFocus;
                textBox.TargetUpdated += TextBox_TargetUpdated;
                textBox.LostFocus += TextBox_LostFocus;
            }
            else
            {
                textBox.GotFocus -= TextBox_GotFocus;
                textBox.TargetUpdated -= TextBox_TargetUpdated;
                textBox.LostFocus -= TextBox_LostFocus;
            }
        }
    }

    private static void TextBox_GotFocus(object sender, RoutedEventArgs e)
    {
        if (sender is TextBox textBox)
        {
            textBox.SelectAll();
        }
    }

    private static void TextBox_TargetUpdated(object sender, DataTransferEventArgs e)
    {
        if (sender is TextBox textBox)
        {
            textBox.Dispatcher.Invoke(() =>
            {
                textBox.Focus();
                textBox.SelectAll();
            });
        }
    }
    private static void TextBox_LostFocus(object sender, RoutedEventArgs e)
    {
        if (sender is TextBox textBox)
        {
            textBox.GotFocus -= TextBox_GotFocus;
            textBox.TargetUpdated -= TextBox_TargetUpdated;
            textBox.LostFocus -= TextBox_LostFocus;
        }
    }
}

修改后的样式与绑定

新编辑样式
<Style
    x:Key="SelectAllTextBoxStyle"
    TargetType="TextBox"
    BasedOn="{StaticResource MahApps.Styles.TextBox.DataGrid.Editing}"
    >
    <Setter
        Property="control:TextBoxBehavior.SelectAllOnGotFocus"
        Value="True"
        />
    <Setter
        Property="mah:TextBoxHelper.ClearTextButton"
        Value="False"
        />
</Style>
更新后的DataGrid列绑定
<DataGridTextColumn
    VirtualizingPanel.VirtualizationMode="Recycling"
    VirtualizingPanel.IsContainerVirtualizable="True"
    VirtualizingPanel.IsVirtualizing="True"
    Header="Precio Unitario"
    VirtualizingPanel.ScrollUnit="Pixel"
    EditingElementStyle="{StaticResource SelectAllTextBoxStyle}"
    Binding="{Binding SALESPRICE, StringFormat='0.000', ConverterCulture=es-ES, IsAsync=True, UpdateSourceTrigger=LostFocus, Mode=TwoWay, ValidatesOnDataErrors=True, NotifyOnTargetUpdated=True}"
    ElementStyle="{StaticResource DataGridTextColumnHorizontalRight}"
    />

最终选择

上述临时方案虽能解决问题,但并非推荐做法,最终将绑定设置回IsAsync=false。

内容的提问来源于stack exchange,提问作者Yago

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 02:17:06