2
votes

I'm trying to create a ListBox with a custom data template but the bindings seem to be wrong. When I try to add items to the list with the PacketItem template they are added, but the text in the three HexItem textboxes remains blank. When I set the item template of the listbox directly to the HexItem data template that works fine. It only has problems when nested in the PacketItem data template.

I'm sure this is a simple fix, it seems like when the template is nested it doesn't know where to look for the text bindings. I'm thinking binding to a relative source to get the data context from a parent would work, but that seems like the wrong way to do it.

Revised XAML

<UserControl x:Class="wpfPacketBox.ctlPacketBox"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:wpfPacketBox"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="600">
    <UserControl.Resources>
        <DataTemplate x:Key="PacketItem">
            <Expander IsExpanded="True"
                      d:DesignWidth="600">
                <Expander.HeaderTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Text="PacketNum" />
                            <TextBlock Text="Source" />
                            <TextBlock Text="Dest" />
                            <TextBlock Text="PacketID (FF0A)" />
                        </StackPanel>
                    </DataTemplate>
                </Expander.HeaderTemplate>
                <Expander.ContentTemplate>
                    <DataTemplate>
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="10*" />
                                <ColumnDefinition Width="65*" />
                                <ColumnDefinition Width="25*" />
                            </Grid.ColumnDefinitions>

                            <Grid Grid.Column="0">
                                <TextBox Text="{Binding Offset}"
                                         FontFamily="Courier New"
                                         Foreground="Blue"
                                         Background="#FFCCCCCC"
                                         TextWrapping="Wrap"
                                         BorderThickness="0" />
                            </Grid>

                            <Grid Grid.Column="1">
                                <TextBox Text="{Binding Hex}"
                                         FontFamily="Courier New"
                                         TextWrapping="Wrap"
                                         BorderThickness="0" />
                            </Grid>

                            <Grid Grid.Column="2">
                                <TextBox Text="{Binding Ascii}"
                                         FontFamily="Courier New"
                                         Background="#FFCCCCCC"
                                         TextWrapping="Wrap"
                                         BorderThickness="0" />
                            </Grid>
                        </Grid>
                    </DataTemplate>
                </Expander.ContentTemplate>
            </Expander>
        </DataTemplate>
    </UserControl.Resources>

    <Grid>
        <ListBox ItemsSource="{Binding Path=Packets}"
                 ItemTemplate="{StaticResource PacketItem}"
                 Grid.Row="1"
                 ScrollViewer.HorizontalScrollBarVisibility="Disabled" />
    </Grid>

</UserControl>

Code

using System;
using System.Windows.Controls;
using System.Collections.ObjectModel;

namespace wpfTester.UserControls
{
    public partial class test : UserControl
    {
        public ObservableCollection<clsPacket> Packets;

        public test()
        {
            InitializeComponent();
            Packets = new ObservableCollection<clsPacket>();
            PacketListBox.ItemsSource = Packets;

            for (int i = 0; i <= 100; i++)
            {
                Packets.Add(new clsPacket() { Offset = i, Hex = "00 11 22 33 44 55 66 77", Ascii = "ABCDEFGH" });
            }
        }
    }

    public class clsPacket
    {
        public long Offset { get; set; }
        public String Hex { get; set; }
        public String Ascii { get; set; }
    }
}

Solution

After some digging I found the solution here. The problem was the expander. I was setting the header/content templates of the expander. But never specified the Header/Content it self. Here's the modified expander tag that fixed my problem.

<Expander IsExpanded="True" Header="{Binding}" Content="{Binding}">
2

2 Answers

2
votes

You need to set the DataTemplates DataType(clsPacket) for the for it to resolve the bindings.

Im not sure what the other DataTemplate is for, but this should point you in the right direction to get your bindings working correctly.

<UserControl x:Class="WpfApplication11.test"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:WpfApplication11"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <UserControl.Resources>
        <DataTemplate DataType="{x:Type local:clsPacket}">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="10*" />
                    <ColumnDefinition Width="65*" />
                    <ColumnDefinition Width="25*" />
                </Grid.ColumnDefinitions>

                <Grid Grid.Column="0">
                    <TextBox Text="{Binding Offset}"
                             FontFamily="Courier New"
                             Foreground="Blue"
                             Background="#FFCCCCCC"
                             TextWrapping="Wrap"
                             BorderThickness="0" />
                </Grid>

                <Grid Grid.Column="1">
                    <TextBox Text="{Binding Hex}"
                             FontFamily="Courier New"
                             TextWrapping="Wrap"
                             BorderThickness="0" />
                </Grid>

                <Grid Grid.Column="2">
                    <TextBox Text="{Binding Ascii}"
                             FontFamily="Courier New"
                             Background="#FFCCCCCC"
                             TextWrapping="Wrap"
                             BorderThickness="0" />
                </Grid>
            </Grid>
        </DataTemplate>
    </UserControl.Resources>

    <Grid>
        <ListBox ItemsSource="{Binding Path=Packets}"
                 Grid.Row="1"
                 ScrollViewer.HorizontalScrollBarVisibility="Disabled" />
    </Grid>

</UserControl>

code:

namespace WpfApplication11
{
    public partial class test : UserControl
    {
        private ObservableCollection<clsPacket> _packets = new ObservableCollection<clsPacket>();

        public test()
        {
            InitializeComponent();
            DataContext = this;
            for (int i = 0; i <= 100; i++)
            {
                Packets.Add(new clsPacket() { Offset = i, Hex = "00 11 22 33 44 55 66 77", Ascii = "ABCDEFGH" });
            }
        }

        public ObservableCollection<clsPacket> Packets
        {
            get { return _packets; }
            set { _packets = value; }
        }
    }

    public class clsPacket
    {
        public long Offset { get; set; }
        public String Hex { get; set; }
        public String Ascii { get; set; }
    }
}
1
votes

After some digging I found the solution here. The problem was the expander. I was setting the header/content templates of the expander. But never specified the Header/Content it self. Here's the modified expander tag that fixed my problem.

<Expander IsExpanded="True" Header="{Binding}" Content="{Binding}">