分组选项更改时保持DataGrid的列宽

时间:2018-03-24 07:43:56

标签: c# data-binding wpf-controls

我一直在使用Rubberduck一段时间来改善我的VBA代码。 ducky向我介绍了单元测试和许多其他适当的技术。感谢我尽管不知道C#而试图回馈并解决我发现的问题。

该问题涉及System.Windows.Controls.Grid。网格可以选择按结果或它们所在的模块对测试结果进行分组。如果调整列宽,然后更改分组,则不会反映宽度变化。

我已经在viewmodel上创建了我认为允许双向绑定的属性,一个在下面作为示例显示。

private DataGridLength _outcomeColumnWidth;
public DataGridLength OutcomeColumnWidth
{
    get => _outcomeColumnWidth;
    set
    {
        _outcomeColumnWidth = value;
        OnPropertyChanged();
    } 
}

我已经编辑了XAML,尝试创建一个TwoWay绑定,在更改分组后,更改的列宽将保持不变。

<Grid>
    <controls:GroupingGrid ItemsSource="{Binding Source={StaticResource ResultsByOutcome}}"
                                SelectedItem="{Binding SelectedTest}"
                                ShowGroupingItemCount="True"
                                Visibility="{Binding IsChecked, ElementName=GroupByOutcome, Converter={StaticResource BoolToVisibility}}">
        <DataGrid.Columns>
            <DataGridTemplateColumn Header="{Resx ResxName=Rubberduck.UI.RubberduckUI, Key=TestExplorer_Outcome}">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate DataType="unitTesting:TestMethod">
                        <Image Source="{Binding Result.Outcome, Converter={StaticResource OutcomeIconConverter}}" Height="16" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
            <DataGridTextColumn Header="{Resx ResxName=Rubberduck.UI.RubberduckUI, Key=TestExplorer_QualifiedModuleName}" Binding="{Binding Declaration.QualifiedName.QualifiedModuleName}"
                                Width="{Binding OutcomeColumnWidth, Mode=TwoWay}"/>
            <DataGridTextColumn Header="{Resx ResxName=Rubberduck.UI.RubberduckUI, Key=TestExplorer_MethodName}" Binding="{Binding Declaration.IdentifierName}"
                                Width="{Binding ModuleColumnWidth, Mode=TwoWay}"/>
            <DataGridTextColumn Header="{Resx ResxName=Rubberduck.UI.RubberduckUI, Key=TestExplorer_Message}" Binding="{Binding Result.Output}"
                                Width="{Binding MessageColumnWidth, Mode=TwoWay}"/>
            <DataGridTextColumn Header="{Resx ResxName=Rubberduck.UI.RubberduckUI, Key=TestExplorer_Duration}" Binding="{Binding Result.Duration, StringFormat={}{0}ms}" 
                                Width="{Binding DurationColumnWidth, Mode=TwoWay}"/>
        </DataGrid.Columns>
    </controls:GroupingGrid>
    <controls:GroupingGrid ItemsSource="{Binding Source={StaticResource ResultsByModule}}"
                                SelectedItem="{Binding SelectedTest}"
                                ShowGroupingItemCount="True"
                                Visibility="{Binding IsChecked, ElementName=GroupByLocation, Converter={StaticResource BoolToVisibility}}">
        <DataGrid.Columns>
            <DataGridTemplateColumn Header="{Resx ResxName=Rubberduck.UI.RubberduckUI, Key=TestExplorer_Outcome}">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate DataType="unitTesting:TestMethod">
                        <Image Source="{Binding Result.Outcome, Converter={StaticResource OutcomeIconConverter}}" Height="16" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
            <DataGridTextColumn Header="{Resx ResxName=Rubberduck.UI.RubberduckUI, Key=TestExplorer_QualifiedModuleName}" Binding="{Binding Declaration.QualifiedName.QualifiedModuleName}" 
                                Width="{Binding OutcomeColumnWidth, Mode=TwoWay}"/>
            <DataGridTextColumn Header="{Resx ResxName=Rubberduck.UI.RubberduckUI, Key=TestExplorer_MethodName}" Binding="{Binding Declaration.QualifiedName.MemberName}" 
                                Width="{Binding ModuleColumnWidth, Mode=TwoWay}"/>
            <DataGridTextColumn Header="{Resx ResxName=Rubberduck.UI.RubberduckUI, Key=TestExplorer_Message}" Binding="{Binding Result.Output}"
                                Width="{Binding MessageColumnWidth, Mode=TwoWay}"/>
            <DataGridTextColumn Header="{Resx ResxName=Rubberduck.UI.RubberduckUI, Key=TestExplorer_Duration}" Binding="{Binding Result.Duration, StringFormat={}{0}ms}"
                                Width="{Binding DurationColumnWidth, Mode=TwoWay}"/>
        </DataGrid.Columns>
    </controls:GroupingGrid>
</Grid>

视图模型继承自实现ViewModelBase的抽象类INotifyPropertyChanged。抽象类还有public event PropertyChangedEventHandler PropertyChanged和方法OnPropertyChanged。我已在getset设置了该属性的断点,但均未达到。

1 个答案:

答案 0 :(得分:0)

DataGrid列不属于逻辑树或可视树,因为它们是抽象对象,因此它们无权访问ViewModel的DataContext。这使得它们很难绑定。好消息是,您几乎没有方法可以做到这一点。

代理对象

<UserControl.Resources>
    <FrameworkElement x:Key="ProxyElement" DataContext="{Binding}" />
</UserControl.Resources>

<Grid>
    <DataGrid ItemsSource="{Binding Descriptions}">
        <DataGrid.Columns>
            <DataGridTextColumn Header="Description"
                                Width="{Binding Source={StaticResource ProxyElement}, Path=Width, Mode=TwoWay}"
                                Binding="{Binding Description}" />
        </DataGrid.Columns>
    </DataGrid>
</Grid>

为了进一步阅读,我建议您看看https://www.thomaslevesque.com/2011/03/21/wpf-how-to-bind-to-data-when-the-datacontext-is-not-inherited/,因为它很好地概述了原因,并提供了使用他创建的特定ProxyClass替代上述代码的方法。