How to set silverlight comboboxitem value in xaml - silverlight

I create a datatemplate for a combobox as follows:
<DataTemplate x:Key="AircraftTypeTemplate">
<StackPanel Orientation="Horizontal" Width="340">
<ComboBox>
<ComboBoxItem>CJ1</ComboBoxItem>
<ComboBoxItem>CJ3</ComboBoxItem>
<ComboBoxItem>Bravo</ComboBoxItem>
<ComboBoxItem>Excel</ComboBoxItem>
<ComboBoxItem>Sovereign</ComboBoxItem>
</ComboBox>
</StackPanel>
</DataTemplate>
It renders fine, but I would like to be able to associate a value with each of the items without having to bind it to some data context. For example I would like the CJ1 comboboxitem to have a value of 5. How would I set those in XAML?
Like:
<ComboBoxItem Value="5">CJ1</ComboBoxItem>
Thanks!

You can set the Name property to be any arbitrary string and use that. For more flexibility, you can use the Tag property, which according to MSDN:
Gets or sets an arbitrary object value that can be used to store custom information about this object.
You can read more about Tag here. I'd say Tag is probably better as opposed to bending Name to your will, and you can stick a string into Tag just as easily as Name.

Related

Can I databind to properties of a custom class (instantiated in xaml) that then forms the content of a templated listboxitem

Any help on this really appreciated. In summary I'm trying to databind to properties of a custom class instantiated in xaml that then forms the content of a templated listboxitem (phew!).
I have a simple c# class called MenuItem. It has two properties:
- Heading
- Icon
Concentrating on just one of those menu items (i.e. to provide a simple example of where I am stuck) If I do this (with the values hard coded) it works fine:
<ListBox>
<ListBoxItem ContentTemplate="{StaticResource MenuItemTemplate}">
<myclasses:MenuItem Heading="News" IconImage="News.png"/>
</ListBoxItem>
</Listbox>
Where MenuItemTemplate is an appropriate DataTemplate in the resources section binding each property) containing lines such as:
<TextBlock x:Name="tbHeading" Text="{Binding Heading}">
Wheareas when I try to use binding to set the Heading property it falls over (AG_E_PARSER_BAD_PROPERTY_VALUE error)- e.g.:
<ListBox>
<ListBoxItem ContentTemplate="{StaticResource MenuItemTemplate}">
<myclasses:MenuItem Heading="{Binding NewsHeading, Mode=OneWay}" Icon="News.png"/>
</ListBoxItem>
<Listbox>
I've wondered if it is because I'm doing some kind of double binding (i.e. the template is binding to a value on the MenuItem class that needs to be bound) and that's not possible? I've tried having the properties declared as dependency properties but no difference (although I only learned about those today so I may be missing something).
I know I could set the menuitem objects up in the view model, and bind from there, but I would like to understand why the above doesn't work (as for my purposes there are advantages in constructing the menu items in the xaml).
Thank you!!!!
Ian
thanks for sticking with this. I agree the listbox might not be needed - but even if I reduce it to just one item in a contentcontrol:
<ContentControl ContentTemplate="{StaticResource MenuItemTemplate}">
<myclasses:MenuItem Heading="{Binding NewsHeading, Mode=OneWay}" IconImage="News.png"/>
</ContentControl>
I still have the same problem - which is that I can get databinding to work within the content of a contentcontrol (prior to it being presented by the datatemplate referred to in ContentTemplate) using purely xaml.
I.e. the above bit of xaml doesn't work - it throws an error on the bit that binds the NewsHeading:
Heading="{Binding NewsHeading, Mode=OneWay}
So I am trying to understand whether what I'm doing is impossible, or whether it is but I'm doing it wrong.
Thanks.
Assuming that you have multiple MenuItem classes (because you're putting them in a listbox and ti wouldn't make sense to do that if you just had one). You need to bind the collection to the ItemsSource property of the ListBox.
Somehting like this:
<ListBox ItemsSource="{Binding MyMenuItems}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Heading}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Note that the above assumes you've set the DataContext on the page to an object with a property called MyMenuItems which is a collection of your MenuItem objects.
To see a full example of this, look at the default code created when you create a new "Windows Phone Databound Application".
Edit:
Based on your comments, it seems that a ListBox is not the most appropriate solution to your needs. A ListBox is designed/intended to take a collection of items and display them in a list.
If you have a number of different objects which you know about at design time and simply wish to have them one on top of another (giving the appearance of a list) you could simply put them inside a ScrollViewer and/or a StackPanel (or other appropriate container). Plus, you would still be able to databind if you did it this way.

What's a good way to parameterize a ValueConverter used in a ControlTemplate?

A templated control I'm working on uses a ValueConverter like so:
<ListBox>
<ListBox.Resources>
<Controls:CodeDescriptionValueConverter x:Key="CodeDescriptionValueConverter"/>
</ListBox.Resources>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Converter={StaticResource CodeDescriptionValueConverter}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
This is the default look that I supply in generic.xaml. When I use this control I'll want to pass different format strings into the converter. Is there a way to make that happen without providing the full ControlTemplate?
My first thought was that I could use ConverterParameter with a TemplateBinding to a property on the control, but I discovered that ConverterParameters can't be bound to. Another option could be to get access to the control from the ConvertTo method, then pick off that property. I'm not sure how to do that. Any options that would eliminate the need to completely re-template the control each time I use it would be helpful (it's a lot of Xaml).
In these situations, I generally do one of two things:
1) Bind to an object that has access to both the property you want to bind to the format string. In the the converter you will then have access to both the property and the format string.
2) Add properties to your data object/viewmodel/etc for the format string and the formatted text. Then bind to the formatted text properties. Assuming that you are using INotifyPropertyChanged, keep in mind that you will need to fire the propertychanged event for the formatted text property whenever you change the text or format string properties

How to access property attributes on a data bound property in Silverlight?

For example, I have a simple textbox bound to a property:
<TextBox Text="{Binding FirstName, Mode=TwoWay, ValidatesOnExceptions=True, NotifyOnValidationError=True}" />
The property looks something like this:
[Display(Name="Last Name")]
public string LastName { ... }
So, given the textbox, I would like to get the Display Name property from the attribute. This will be used in a composite control that includes a fieldlabel and some other niceties.
Thanks in advance.
I am not able to attempt this at the moment so this may not be accurate or even possible. As soon as I get to a computer that I can try this I will...until then, this is just theory.
I'm guessing in your composite control you'll have something like this for each data bound field:
<TextBlock Text="{Binding FirstName, Mode=OneWay}" />
<TextBox Text="{Binding FirstName, Mode=TwoWay, ...}" />
What you'll probably need to do in order to create a converter that will look at the binding data for the Display attribute, and convert the value to the attribute value instead. This would cause the above block to look like this:
<TextBlock Text="{Binding FirstName, Mode=OneWay, Converter={StaticResource AttributeConverter}, ConverterParameter=Display}" />
<TextBox Text="{Binding FirstName, Mode=TwoWay, ...}" />
Here I passed in the Display as the parameter in case you wanted to access a different attribute.
Again this is just theory since I'm not able to currently test this and cannot recall if IValueConverter.Convert(object value, ...) passes the object in question or just the string value in this case. If it's just the string value, it probably isn't possible, though if it's the object instead, it will depend on how much access you have to the reflection namespace to evaluate the attributes.
As soon as I am able to, I'll throw the scenario together and try it out.
EDIT:
For some reason the sytax highlighter is giving me the finger when I try to paste code in this edit
Anyways, after trying this out in a little project, it don't think you can do this.
Based on my suggestion of making 2 data bound controls and using a converter for the one that consumes the attribute, I did the following:
Created the xaml for the databound control.
Create the Custom Attribute for testing
Created the Model with the decorated property for testing.
Created the converter to attempt to read the attribute from the property.
Here's where I got caught up. I wasn't able to obtain the data bound type from the IValueConverter.Convert(...) method. The value parameter came through as String as did the targetType parameter. While that was the primary hangup, the second was that I was unable to dynamically identify the property name that the control was data bound to. This could be remedied through a converter parameter possibly.
Now, I WAS able to read the attribute value if I supplied the type of my test Model with the decorated property so that much is possible but I wasn't able to dynamically identify the type on the fly.
The only other way I can think of is create some form of observer or converter prior to the data truly being bound to your custom control.
Good Luck

x:Name attribute does not always create member or field variable

Adding an x:Name attribute to a XAML element normally results in a member variable being added to the backing class that can then be accessed using normal code. When the element in question is part of the DataTemplate, the field does not get created.
I can sort of understand that the DataTemplate is making this a special case but can anyone explain the underlying principle to me? Also what are the options for getting access to the object within .NET Code?
<dataControls:DataForm x:Name="CompanyDetail" CurrentItem="{Binding CurrentItem}" AutoGenerateFields="False">
<dataControls:DataForm.EditTemplate>
<DataTemplate>
<StackPanel dataControls:DataField.IsFieldGroup="True">
<dataControls:DataField Label="About">
<Border Height="150" Style="{StaticResource HtmlPlaceHolderBorderStyle}" Width="298" VerticalAlignment="Top">
<telerik:RadHtmlPlaceholder x:Name="uxAboutHtml" x:FieldModifier="Public" HtmlSource="{Binding About, Mode=TwoWay}"/>
</Border>
</dataControls:DataField>
</StackPanel>
</DataTemplate>
</dataControls:DataForm.EditTemplate>
</dataControls:DataForm>
You can use the FrameworkElement.FindName("objectName") method on the parent of the DataTemplate e.g. var uxAboutHtml = CompanyDetail.FindName("uxAboutHtml"); to get a reference to the object. The downside to this is that paramater passed to FindName does not end up being strongly typed with the XAML x:Name"objectName" attribute.
I have changed tack on this and am now referencing the underlying object that the control is being bound to, which is probably a better way to go.
var htmlContent = (CompanyViewModel)CompanyDetail.CurrentItem;

WPF: Listbox, valueconverter

What is the easiest way to use a valueconverter with a listbox?
I'm setting the ItemSource to a List<> of objects at runtime, and it displays a textstring from the ToString() method. What I would like, though, is to pass the object through a valueconverter to get a completely different string value.
All the examples I have found makes a big deal of binding the list to something in xaml, and defining styles and templates to redesign the whole box, but I just want my values converted...
Use a data template with something like:
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Converter=....}" />
</...>
That's it. When you don't specify a path in your binding, it simply binds to the current object.

Resources