Изменение Visiblity для DataGridTemplateColumn работает только в первый раз - PullRequest
2 голосов
/ 29 февраля 2012

Я смотрел на ответ о том, как установить видимость столбца сетки данных , поэтому я добавил

 <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>

[EDIT] Вот несколько первых строк из трассировки стека исключений.Всего 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)

Ответы [ 3 ]

2 голосов
/ 10 мая 2013

У меня была похожая проблема, и после глубокого исследования я нашел следующую ветку - Удалите столбец из таблицы данных и добавьте его снова . Автор поста (Jeromeyers) делится:

"Если я закомментирую код, который создает заголовок столбца как TextBlock, то все работает нормально. Итак, именно заголовок столбца каким-то образом хочет сменить родителя, или что-то в этом роде.

PS> Причина, по которой я хочу, чтобы заголовок столбца был TextBlock, заключается в том, что я могу получить перенос текста. "

1 голос
/ 14 сентября 2012

Следующее, кажется, работает, но использует вызов UpdateLayout на DataGrid в коде позади.

После того, как столбец изменится с Collapsed / Hidden на Visible, вызовите UpdateLayout на DataGrid и поймайте исключение.

1 голос
/ 29 февраля 2012

Как я понимаю вашу проблему, вы хотите установить видимость столбцов сетки во время выполнения. Вы можете создать вложенное свойство и связать его столбцами сетки.

(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) Как это работает с сеткой

<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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...