WPF ItemSource DataGrid TreeViewItem ошибка дополнительной строки

1

Я вижу странное поведение: у меня есть TreeViewItem, связанный с источником с несколькими строками:

<TreeViewItem Name="TreeViewItem1" >                                    
    <TreeViewItem.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding IP,FallbackValue=BindingError,Mode=TwoWay}" />
        </DataTemplate>
    </TreeViewItem.ItemTemplate>
</TreeViewItem>

Связанный во время выполнения с этим кодом:

TreeViewItem1.ItemsSource = MySource;

До сих пор он работает так, как ожидалось: скажем, у меня есть 2 строки на MySource - TreeViewItem показывает 2 дочерних узла с правильными значениями, заполненными. Затем я связываю DataGrid аналогично тому же источнику:

<DataGrid Grid.Row="0" Name="MyDataGrid" AutoGenerateColumns="False" CanUserDeleteRows="True" >
    <DataGrid.Columns>
        <DataGridTextColumn x:Name="IP" Binding="{Binding IP}" Header="IP" />
        <DataGridTextColumn x:Name="Port" Binding="{Binding Port}" Header="Port" />
    </DataGrid.Columns>
</DataGrid>

с кодом

MyDataGrid.Items.Clear();
MyDataGrid.ItemsSource = MySource;

DataGird имеет 3 строки: 2 из MySource с заполненными правильными значениями и еще один для добавления строк.

ПРОБЛЕМА: это то, что в этот момент TreeViewItem ТАКЖЕ получает 3d-ребенка, хотя MySource все еще имеет только 2. Это не имеет смысла, но то, что я вижу. Как если бы оба DatGrid и TreeViewItem были привязаны не к MySource, а к некоторой внутренней структуре, имитирующей ее, которая разделяется между двумя элементами управления.

Вероятно, это не имеет значения, но для записи MySource является ObservableCollection с каждым элементом, реализующим INotifyPropertyChanged, поэтому добавление/удаление строк, а также изменение значений для каждой строки должным образом обновляются на обоих элементах управления. Единственная проблема заключается в дополнительной строке в TreeViewItem.

Теги:
wpf
datagrid
treeviewitem

1 ответ

0

Вы пытались установить:

CanUserAddRows="False"

К вашей сетке данных? Я всегда устанавливал это, а затем использовал кнопку для добавления строк в мои сетки данных. С моей точки зрения, это имеет смысл для наших бизнес-пользователей.

Если это не сработает для вас, вы также не можете привязать свои datagrid и treeview к одной и той же наблюдаемой коллекции, а затем сохранить синхронизируемую коллекцию дерева просмотра.

Другое Редактировать Это все еще не идеальное решение, но ваш вопрос вызвал мой интерес. Я все еще поклонник кнопок, нажимающих кнопки для добавления элементов;). Вот что я нашел.

Если я установил источник TreeViewItem в виде коллекции таким образом:

Окно Xaml:

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525" Background="Red" >
<Window.Resources>
            <CollectionViewSource x:Key="TreeViewCollection" Source="{Binding AllRoles, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}"/>
</Window.Resources>
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="57*"/>
        <RowDefinition Height="125*"/>
        <RowDefinition Height="138*"/>
    </Grid.RowDefinitions>
    <TreeViewItem Name="TreeViewItem1" Background="White" Grid.RowSpan="3" IsExpanded="True" ItemsSource="{Binding Source ={StaticResource TreeViewCollection}}">
        <TreeViewItem.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding ip,FallbackValue=BindingError,Mode=TwoWay}" />
            </DataTemplate>
        </TreeViewItem.ItemTemplate>
    </TreeViewItem>
    <DataGrid Grid.Row="2" Name="MyDataGrid" AutoGenerateColumns="False" CanUserDeleteRows="True" CanUserAddRows="True"
              ItemsSource="{Binding AllRoles, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}">
        <DataGrid.Columns>
            <DataGridTextColumn x:Name="IP" Binding="{Binding ip}" Header="IP" />
        </DataGrid.Columns>
    </DataGrid>
</Grid>

Код:

namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    public ObservableCollection<Role> AllRoles { get; private set; }

    public MainWindow()
    {
        this.InitializeComponent();
        var allRoles = new ObservableCollection<Role>();
        allRoles.Add(new Role{ip = "bob"});
        allRoles.Add(new Role{ip = "john"});
        this.AllRoles = allRoles;

        TreeViewItemSource = GetNonsCollectionView(allRoles);
    }

    public CollectionView DataGridViewSource { get; private set; }
    public CollectionView TreeViewItemSource { get; private set; }

    public CollectionView GetNonsCollectionView(ObservableCollection<Role> nonsList)
    {
        return (CollectionView)CollectionViewSource.GetDefaultView(nonsList);
    }
}

public class Role : INotifyPropertyChanged
{
    public string ip { get; set; }
    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

}

Вы увидите, что это работает. Проблема, которую я вижу в настоящее время, обновляет представление коллекции, когда пользователь добавляет новую строку в сетку, задавая фокус. Я устал, иначе я бы углубился дальше.

Вот некоторые ссылки, которые я нашел на этом пути.

Комментарии сотрудника MSFT по аналогичной проблеме выглядят так, как будто мое второе решение выше.

Гай на форуме MSFT описывает проблему

Я всегда думал, что я порядочный в WPF, я понятия не имел...

  • 0
    Нет, потому что я хочу, чтобы пользователи добавляли строки. Это должно быть ясно из моего вопроса, так как я отмечаю, что DataGrid имеет дополнительную строку и возражает только против TreeViewItem, получающего один ТАКЖЕ.
  • 0
    Вы можете добавить кнопку, которая добавит строку в вашу сетку, чтобы пользователь мог заполнить соответствующую информацию. То же самое с удалением строк. Извинения за неправильное понимание цели вашего вопроса.
Показать ещё 4 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню