Powered by MSDN

US - English
NEW! Silverlight 5 is available Learn More

DataForm - EditTemplate - ComboBox - ItemsSource Bindin... RSS

4 replies

Last post Aug 14, 2009 07:05 PM by Casimodo72

(0)
  • Casimodo72

    Casimodo72

    Participant

    1060 Points

    467 Posts

    DataForm - EditTemplate - ComboBox - ItemsSource Binding does not honor Source

    Aug 14, 2009 05:18 PM | LINK

    Hi, 
    I'm currently trying to generate data templates for the DataForm programmatically using the XamlReader.
    In conjunction with ComboBoxes I stumbled upon the following issue:
    <ComboBox
    SelectedItem="{Binding MyValue, Mode=TwoWay}"
    ItemsSource="{Binding Items, Source={StaticResource MyList}}" />
    The ItemsSource does *not* bind to the static resource "MyList", but to the data context.
    I.e. it does not honor the "Source={StaticResource MyList}".
    I'm getting the following error: 
    BindingExpression path error: 'Items' property not found on
    'DataFormComboBox.MyData' 'DataFormComboBox.MyData' (HashCode=1723181).
    BindingExpression: Path='Items' DataItem='DataFormComboBox.MyData'
    (HashCode=1723181); target element is
    'System.Windows.Controls.ComboBox' (Name=''); target property is
    'ItemsSource' (type 'System.Collections.IEnumerable')..
     
    Any clues?
    I'm stuck here, since I don't know how to provide lookup-data to my ComboBoxes. 

    My scenario: 
    namespace DataFormComboBox
    {
    public class MyData
    {
    public string MyValue { get; set; }
    }

    public class MyList
    {
    public MyList()
    {
    this.Items = new ObservableCollection<string>();
    foreach (var item in new string[] { "One", "Two", "Three" })
    this.Items.Add(item);
    }

    public ObservableCollection<string> Items { get; private set; }
    }

    public partial class MainPage : UserControl
    {
    public MainPage()
    {
    InitializeComponent();
    this.LayoutRoot.Resources.Add("MyList", new MyList());
    this.DataContext = new MyData();
    }
    }
    }
     
    <UserControl
    x:Class="DataFormComboBox.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:df="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.DataForm.Toolkit"
    mc:Ignorable="d"
    d:DesignWidth="640"
    d:DesignHeight="480">
    <Grid
    x:Name="LayoutRoot">
    <df:DataForm
    AutoGenerateFields="False"
    AutoEdit="True"
    CurrentItem="{Binding}">
    <df:DataForm.EditTemplate>
    <DataTemplate>
    <StackPanel>
    <df:DataField>
    <ComboBox
    SelectedItem="{Binding MyValue, Mode=TwoWay}"
    ItemsSource="{Binding Items, Source={StaticResource MyList}}" />
    </df:DataField>
    </StackPanel>
    </DataTemplate>
    </df:DataForm.EditTemplate>
    </df:DataForm>
    </Grid>
    </UserControl>

     

    Regards,

    Kasimier

  • Casimodo72

    Casimodo72

    Participant

    1060 Points

    467 Posts

    Re: DataForm - EditTemplate - ComboBox - ItemsSource Binding does not honor Source

    Aug 14, 2009 05:57 PM | LINK

    Actually the above example scenario does not reflect my issue exactly,

    since I learned that - for the above example - I just need to add the resource

    prior to InitializeComponent() in order to make the ComboBox's ItemsSource bind correctly to my resource:

    this.Resources.Add("MyList", new MyList());
    InitializeComponent();
    this.DataContext = new MyData();
    It seems that the binding didn't find the resource and fell back to the data context.
    Is this behaviour by design? I.e. silently performing a fall back although
    the Source was explicitely set to a resource?
     
    My actual scenario looks more like this:
    namespace DataFormComboBox
    {
    public class MyData
    {
    public string MyValue { get; set; }
    }

    public class MyList
    {
    public MyList()
    {
    this.Items = new ObservableCollection<string>();

    foreach (var item in new string[] { "One", "Two", "Three" })
    this.Items.Add(item);
    }

    public ObservableCollection<string> Items { get; private set; }
    }

    public partial class MainPage : UserControl
    {
    public MainPage()
    {
    this.Resources.Add("MyList", new MyList());
    InitializeComponent();
    this.DataContext = new MyData();

    MyDataForm.EditTemplate = BuildTemplate();
    MyDataForm.ApplyTemplate();
    }

    DataTemplate BuildTemplate()
    {
    // This would be the generated XAML.
    string xaml = @"&lt;DataTemplate
    xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
    xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
    xmlns:df='clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.DataForm.Toolkit'>
    <StackPanel>
    <df:DataField>
    <ComboBox
    SelectedItem='{ Binding MyValue, Mode=TwoWay }'
    ItemsSource='{ Binding Items, Source={StaticResource MyList } }' />
    </df:DataField>
    </StackPanel>
    </DataTemplate>"
    ;

    DataTemplate template = (DataTemplate)XamlReader.Load(xaml);

    return template;
    }
    }
    }
      
    <UserControl
    x:Class="DataFormComboBox.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:df="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.DataForm.Toolkit"
    mc:Ignorable="d"
    d:DesignWidth="640"
    d:DesignHeight="480">
    <Grid
    x:Name="LayoutRoot">
    <df:DataForm
    x:Name="MyDataForm"
    AutoGenerateFields="False"
    AutoEdit="True"
    CurrentItem="{Binding}">
    </df:DataForm>
    </Grid>
    </UserControl>
     
    Does this mean that when loading the XAML with XamlReader
    the binding to the resource is discarded somehow, since there are no resources in
    scope at that time? Somehow I expected such references to be resolved when
    the template is added to the visual tree, i.e. when performing the following:
    MyDataForm.EditTemplate = BuildTemplate();
    MyDataForm.ApplyTemplate();
    Any clues? 
    Regards,
    Kasimier 
     
  • lee_sl

    lee_sl

    Contributor

    4222 Points

    864 Posts

    Re: Re: DataForm - EditTemplate - ComboBox - ItemsSource Binding does not honor Source

    Aug 14, 2009 06:11 PM | LINK

    I am not sure why you want to add it to Resources in codebehind and get it from resources.

    you can add Contentloaded event handler and get the combobox  and set the Itemssource directly to your list

    ----------------------------------------------
    Available for consulting in Dallas, TX
    http://leeontech.wordpress.com/
  • Casimodo72

    Casimodo72

    Participant

    1060 Points

    467 Posts

    Re: Re: DataForm - EditTemplate - ComboBox - ItemsSource Binding does not honor Source

    Aug 14, 2009 06:13 PM | LINK

    Related posts (problems with StaticResource used in dynamically generated DataTemplates):

    http://silverlight.net/forums/t/70078.aspx

    http://silverlight.net/forums/t/62926.aspx

  • Casimodo72

    Casimodo72

    Participant

    1060 Points

    467 Posts

    Re: Re: DataForm - EditTemplate - ComboBox - ItemsSource Binding does not honor Source

    Aug 14, 2009 07:05 PM | LINK

     @lee_sl : Great, setting the ItemsSource in ContentLoaded of the DataForm works fine.

    Thanks for the tip.

     

    Actually I would love to be able to create the whole template

    programmatically without resorting to the XamlReader thingy.

    But that's not supported in Silverlight.

     

    The workaround (using ContentLoaded) is still awkward:

    1) I have to use the XamlReader for DataTemplate creation, but cannot use StaticResource in such XAMLs.

    2) I need to post-process the elements in such DataTemplates when the templates are applied.

       This means that setting e.g. Converters on Bindings needs also be done here.

     

    This is currently not a problem for me, because I'm using a kind of descriptor/builder/manager

    for DataTemplate generation and integration with the DataForm.

    Something along the following lines:

    MembershipServiceUser user = MembershipServiceUser.Create();

    LookupDataSource sourceA =
    new LookupDataSource(
    () => new string[] { "Kasimier", "Uwe", "Christa" }
    );

    LookupDataSource sourceB =
    new LookupDataSource(
    () => new string[] { "me@casimodo.net", "you@casimodo.net", "her@casimodo.net" }
    );

    EntityPresentationDescriptor<MembershipServiceUser> descriptor =
    new EntityPresentationDescriptor<MembershipServiceUser>();

    descriptor.AddLookupSource(sourceA);
    descriptor.AddLookupSource(sourceB);

    descriptor
    .AddProperty(o => o.UserName, sourceA)
    .AddProperty(o => o.Email, sourceB);

    This description is then applied to a DataForm by a manager.

     

    But when someone actually writes DataTemplates in XAML, where's the fun then?


    Thanks & regards,

    Kasmier