3

I am trying to create a ListBox view for show data, and I want it to contain a ListBox with a datatemplate for 2 columns "Product ID & Product Barcode"

I want to create it either using pure C# code or if possible load it through xaml? If I can create a template I can get in c# as a resource of sorts.

What I have made until now is: In XAML :

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="37*" />
        <RowDefinition Height="88*" />
    </Grid.RowDefinitions>
    <TextBlock Text="Type Your Search :" HorizontalAlignment="Left"  VerticalAlignment="Bottom" Width="112" Height="15.96" Margin="20,0,0,4" />

    <TextBox HorizontalAlignment="Right" VerticalAlignment="Bottom" Height="25" Width="300" Margin="0,0,44,0" x:Name="txtCAuto" TextWrapping="NoWrap" HorizontalContentAlignment="Right" />

    <ListBox x:Name="lbSuggestion" SelectionChanged="lbSuggestion_SelectionChanged" Foreground="Black" Width="300" Margin="0,0,44,0"  FlowDirection="RightToLeft" Background="LightYellow" Grid.Row="1" Visibility="Collapsed"  ScrollViewer.HorizontalScrollBarVisibility="Auto" ItemsSource="{Binding}"  HorizontalAlignment="Right" VerticalAlignment="Top" HorizontalContentAlignment="Right" BorderBrush="Transparent"  Grid.IsSharedSizeScope="True">
    </ListBox>
</Grid>

In Code Behind:

string typedString = txtCAuto.Text.ToUpper();
        List<string> autoList = new List<string>();
        autoList.Clear();

         prodDetails ps = SelProd4Sale();

        foreach (string item in ps.ProdBrcdList)
        {
            if (!string.IsNullOrEmpty(txtCAuto.Text))
            {
                if (item.StartsWith(typedString))
                {
                    //autoList.Add(item);
                    FrameworkElementFactory colProdID = new FrameworkElementFactory(typeof(TextBlock));
                    Binding prodID = new Binding(ps.ProdIDList.ToString());
                    colProdID.SetBinding(TextBlock.TextProperty, prodID);

                    FrameworkElementFactory colProdBarcode = new FrameworkElementFactory(typeof(TextBlock));
                    Binding prodBarcode = new Binding();
                    prodBarcode.Path = new PropertyPath(ps.ProdBrcdList.ToString());
                    colProdBarcode.SetBinding(TextBlock.TextProperty, prodBarcode);


                    FrameworkElementFactory sb = new FrameworkElementFactory(typeof(StackPanel));
                    sb.AppendChild(colProdID);
                    sb.AppendChild(colProdBarcode);

                    dTemplate = new DataTemplate { VisualTree = sb };
                    dTemplate.Seal();


                }
            }
        }

        if (autoList.Count > 0)
        {
            lbSuggestion.ItemTemplate = dTemplate;
            //lbSuggestion.ItemsSource = autoList;
            lbSuggestion.Visibility = Visibility.Visible;
        }
        else if (txtCAuto.Text.Equals(""))
        {
            lbSuggestion.Visibility = Visibility.Collapsed;
            lbSuggestion.ItemsSource = null;
        }
        else
        {
            lbSuggestion.Visibility = Visibility.Collapsed;
            lbSuggestion.ItemsSource = null;
        }

but there is no data appears, any suggestion please. thanks,

Love_Egypt
  • 179
  • 4
  • 6
  • 16

3 Answers3

8

You can define resources in xaml and retrieve it in code behind if it has an x:Key defined.

In your xaml :

<DataTemplate x:Key="anyId">...</DataTemplate>

And in your code behind :

var dataTemplate = Application.Current.TryFindResource("anyId") as DataTemplate;

or

var dataTemplate = Application.Current.FindResource("anyId") as DataTemplate;
Sisyphe
  • 4,626
  • 1
  • 25
  • 39
  • 1
    You have to write the DataTemplate in a resource dictionary in a XAML file and set the x:Key yourself ! What I meant is that you jsut have to set an x:Key parameter to be able to retrieve any resource in code behind. – Sisyphe Dec 27 '12 at 15:38
  • Good answer. Allows you to define the datatemplate in XAML where it belongs, then use it when necessary. – Josh Apr 17 '13 at 17:50
4

I have created DataTemplate like this:

private DataTemplate getDataTemplate()
{
    DataTemplate retVal = null;
    String markup = String.Empty;

    markup = "<DataTemplate xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\" xmlns:local=\"clr-namespace:YOUR.PROJECT.NAMESPACE;assembly=YOUR.PROJECT.NAMESPACE\">";
    markup += "<Grid>";
    markup += "<TextBlock Text=\"{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Content, Mode=OneWay}\" />";
    markup += "</Grid>";
    markup += "</DataTemplate>";

    retVal = (DataTemplate)XamlReader.Load(markup);

    return retVal;
}

...and then call this method where you need it (like OnApplyTemplate)

this.ContentTemplate = getDataTemplate();

NOTE : You may have to change the "xmlns" for WPF, because this example is taken from one of my Silverlight projects. But the idea is the same.

Mats Magnem
  • 1,375
  • 1
  • 10
  • 21
  • 1
    A comment is that the best practice in my opinion is to create it in XAML, but I chose to illustrate how it is done in code as the question says :-) – Mats Magnem Dec 27 '12 at 12:49
  • when I try to create it in XAML, no data appears, so do it in code behind – Love_Egypt Dec 27 '12 at 15:24
1

Conditional XAML DataTemplate

Defining a static DataTemplate in your object's XAML file is the customary way to approach this. Also, the example Microsoft provides for DataTemplate.LoadContent() is nifty for showing how to switch templates dynamically at run-time (see DataTemplate.LoadContent method) when needed.

However, if you have a special requirement of conditional XAML compilation (like omitting debug-only XAML when you're building a Release version), you will need to resort to the XamlReader.Load() approach (see XamlReader.Load method).

To that end, I thought a bit more detailed example might be helpful. Here, I have a debug-only ListView that is bound to an ObservableCollection<> of custom objects. The ListView is not defined in static XAML, since it's needed only in Debug mode ...


Custom class:

    class ActiveNotification
    {
        public String Name { get; set; }
        public String Type { get; set; }
        public String DayOfWeek { get; set; }
        public DateTime DeliveryTime { get; set; }
        public String Id { get; set; }
    }

Private member variables:

    readonly ObservableCollection<ActiveNotification> _activeNotifications = new ObservableCollection<ActiveNotification>();
    readonly ListView listViewNotifications = 
        new ListView 
        { 
            Visibility = Visibility.Collapsed,
            HorizontalAlignment = HorizontalAlignment.Left,
            VerticalAlignment = VerticalAlignment.Bottom,
        };

Load-time ListView setup:

        // Set up notifications list
        listViewNotifications.SetBinding(ListView.ItemsSourceProperty, new Binding { Source = _activeNotifications });
        listViewNotifications.Tapped += listViewNotifications_Tapped;
        Grid.SetRowSpan(listViewNotifications, 2);
        Grid.SetColumnSpan(listViewNotifications, 2);
        var xamlString =
            "<DataTemplate xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\">" +
                "<StackPanel Orientation=\"Horizontal\" VerticalAlignment=\"Center\">" +
                    "<TextBlock Text=\"{Binding Name}\" Margin=\"20,0,10,0\"/>" +
                    "<TextBlock Text=\"{Binding Type}\" Margin=\"0,0,10,0\"/>" +
                    "<TextBlock Text=\"{Binding DayOfWeek}\" Margin=\"0,0,10,0\"/>" +
                    "<TextBlock Text=\"{Binding DeliveryTime}\" Margin=\"0,0,10,0\"/>" +
                    "<TextBlock Text=\"{Binding Id}\"/>" +
                "</StackPanel>" +
            "</DataTemplate>";
        var dataTemplate = (DataTemplate)XamlReader.Load(xamlString);
        listViewNotifications.ItemTemplate = dataTemplate;
        GridMain.Children.Add(listViewNotifications);
Dharman
  • 30,962
  • 25
  • 85
  • 135
Mark Jones
  • 2,024
  • 1
  • 19
  • 12