我正在看answer on how to set the visibility of a data grid column,所以我添加了
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="b2v" />
</UserControl.Resources>
然后在我的xaml中我有
<DataGridTemplateColumn Visibility="{Binding Source={x:Reference ShowLookupCheckbox},
Path=IsChecked
Converter={StaticResource b2v}}" >
...
</DataGridTemplateColumn>
当我的应用启动并且复选框已清除时,列已正确折叠。当我选中复选框时,列正确显示。当我再次单击该复选框时,列再次正确折叠。 然而,当我点击第二次启用复选框时,我会收到InvalidOperationException
“指定元素已经是另一个元素的逻辑子元素。首先断开它。”
我尝试将模式改为单向,但这没有用。任何人都知道我做错了什么或如何解释这个例外?
我不认为列的内容在没有可见性设置的情况下正常工作,但为了完成起见,这里是我完全忽略的完整xaml ...上面
<DataGridTemplateColumn.Header>
<TextBlock Style="{StaticResource DataGridHeader}">MO Lookup</TextBlock>
</DataGridTemplateColumn.Header>
<DataGridTemplateColumn.CellTemplate >
<DataTemplate >
<Hots:AutoCompleteBoxEx ToolTip="Start typing a Master Order Id"
ItemsSource="{Binding AllMoLines,
UpdateSourceTrigger=PropertyChanged}"
Width="50"
HorizontalContentAlignment="Left"
FilterMode="StartsWith"
IsDropDownOpen="True"
IsTextCompletionEnabled="True"
LostFocus="MoLineBoxLostFocus"
SelectedItem="{Binding Path=SelectedMoLine, Mode=TwoWay}" >
<Hots:AutoCompleteBoxEx.ItemTemplate>
<DataTemplate>
<Grid Width="500">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50" />
<ColumnDefinition Width="400" />
<ColumnDefinition Width="50" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding HssId, Mode=OneWay}"
Grid.Column="0" />
<TextBlock Text="{Binding Description, Mode=OneWay}"
Grid.Column="1" />
<TextBlock Text="{Binding Unit, Mode=OneWay}"
Grid.Column="2" />
</Grid>
</DataTemplate>
</Hots:AutoCompleteBoxEx.ItemTemplate>
</Hots:AutoCompleteBoxEx>
</DataTemplate>
[编辑] 以下是Exception堆栈跟踪的前几行。整件事是66行。这是我觉得困惑的AddLogicalChild和ChangeLogicalParent。我不确定为什么选中/取消选中链接到Visibility属性的复选框会导致添加子元素
System.InvalidOperationException was unhandled
Message=Specified element is already the logical child of another element. Disconnect it first.
Source=PresentationFramework
StackTrace:
at System.Windows.FrameworkElement.ChangeLogicalParent(DependencyObject newParent)
at System.Windows.FrameworkElement.AddLogicalChild(Object child)
at System.Windows.Controls.ContentControl.OnContentChanged(Object oldContent, Object newContent)
答案 0 :(得分:2)
我遇到了类似的问题,经过深入研究后,我找到了以下帖子 - Remove a column from datagrid and add it back again。 该帖子的作者(Jeromeyers)分享:
“如果我将创建Column's Header的代码注释为TextBlock,那么一切正常。因此,Column的HeaderContent以某种方式想要切换父母或其他东西。
PS&GT;我希望Column的Header成为TextBlock的原因是我可以进行文本换行。“
答案 1 :(得分:1)
据我了解您的问题,您希望在运行时设置网格列的可见性。 您可以创建附加属性并将其与网格列绑定。
(1)附属物
public class GridColumnManager
{
static GridColumnManager()
{
//Allows to set DataContextProperty on the columns. Must only be invoked once per application.
FrameworkElement.DataContextProperty.AddOwner(typeof(DataGridColumn));
}
public static object GetDataContextForColumns(DependencyObject obj)
{ return obj.GetValue(DataContextForColumnsProperty); }
public static void SetDataContextForColumns(DependencyObject obj, object value)
{ obj.SetValue(DataContextForColumnsProperty, value); }
/// <summary>
/// Allows to set DataContext property on columns of the DataGrid (DataGridColumn)
/// </summary>
/// <example><DataGridTextColumn Header="{Binding DataContext.ColumnHeader, RelativeSource={RelativeSource Self}}" /></example>
public static readonly DependencyProperty DataContextForColumnsProperty =
DependencyProperty.RegisterAttached(
"DataContextForColumns",
typeof(object),
typeof(GridColumnManager),
new UIPropertyMetadata(OnDataContextChanged));
/// <summary>
/// Propogates the context change to all the DataGrid's columns
/// </summary>
private static void OnDataContextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var grid = d as DataGrid;
if (grid == null) return;
var name = grid.Name;
foreach (DataGridColumn col in grid.Columns)
col.SetValue(FrameworkElement.DataContextProperty, e.NewValue);
}
}
(2)它如何与Grid一起使用
<DataGrid CanUserAddRows="True" IsEnabled="True" AutoGenerateColumns="False" CanUserDeleteRows="True" IsSynchronizedWithCurrentItem="True" Height="200"
local:GridColumnManager.DataContextForColumns="{Binding Mode=OneWay}" HorizontalAlignment="Left" Margin="80,90,0,0"
Name="dataGrid1" VerticalAlignment="Top" Width="361" ItemsSource="{Binding Employees,Mode=TwoWay,NotifyOnSourceUpdated=True}" >
<DataGrid.Resources>
<BooleanToVisibilityConverter x:Key="MyConvertor"/>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTemplateColumn Header="Stating Period" MinWidth="200" Width="*" Visibility="{/*Bind here with your element */,
RelativeSource={RelativeSource Self},
Converter={StaticResource MyConvertor}}">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding ID}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<TextBox Text="{Binding ID, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True}" />
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn> </DataGrid.Columns>
</DataGrid>
答案 2 :(得分:1)
以下内容似乎有效,但它在后面的代码UpdateLayout
上使用了对DataGrid
的调用。
在列从Collapsed
/ Hidden
更改为Visible
后,请在UpdateLayout
上调用DataGrid
并捕获异常。