Xaml: Itemssource binding + fallbackValue - silverlight

I've got a Listpicker with a DataBinding on the Itemssource-Property. Binding works fine. Now I want to define a FallbackValue. My problem is, that the FallbackValue is interpreted as a list: {'S','t','a','n','d','a','r','d'}, not as a single item 'Standard'. I'm looking for a solution to solve this problem. Any idea?
<toolkit:ListPicker x:Name="listPicker" ExpansionMode="FullScreenOnly" ItemsSource="{Binding Profilelist, ElementName=userControl, FallbackValue='Standard'}" SelectedIndex="0" />

The fallback behaviour is correct as the target expects an array (and a string an usable as an array of chars). There is no easy way to specify an array for the fallback.
I would suggest binding to a ViewModel list, instead of directly to the other control, so you can specify whatever default you want in the list. It does mean an extra binding and a property on your ViewModel (or code-behind... yuk) but element binding is not designed to have a fallback array, only single values.
If you can provide more code/Xaml I will be able to be more specific.

Related

WPF: How to bind to only one item in a collection, not using ItemsControl since I don't want to display all of them

I have this requirement, that I have a collection of items (ObservableCollection), but I only want to display the first item. The requirement comes from the fact that in most of the case, the collection only contains one item. And due to the space limit, even if there is more than one items in the collection, we'd like to display the number of the items, details of the first one (same presentation as prior situation) and a ... symbol to indicate to the user that there is more items. And when the mouse is over the UI element a popup will eventually display all items.
The first solution I can think of (please suggest others if they are better) is to bind to this collection (but not using an ItemsControl) and define a DataTemplateSelector derived class (which return either the DataTemplate to display the only one item, or the DateTemplate which has the ... and the popup for more details, based on the number of items in the collection) and use it as ContentTemplateSelector.
But now my question: how both of my DataTemplate would look like in XAML, so that they can display only the first item in the collection? Obviously I can't have a ItemsControl.
UPDATE:
Now I have managed to make it work and agree this question can be closed (I can't delete it anymore since there is already some answers).
I actually knew how to bind to one certain item in the collection, but this was not where I am confused. I felt I should use ContentControl as one answer suggests. But I thought since I need to bind to the whole collection (not to single indexed item), and use a DataTemplateSelector to select the proper DataTemplate based on the number of items in the collection. The code would look like this:
<ContentControl Content="{Binding MyCollection}"
ContentTemplateSelector="{StaticResource MyTemplateSelector}" />
And in MyTemplateSelector I wasn't sure how to use it since there is no reference to my collection because it is defined as resource and it doesn't have the information of MyCollection. However, it turned out to be very simple, the DataTemplate can refer to an indexed item without knowing the name or any other reference. Simply like this:
<DataTemplate>
<TextBlock Text="{Binding [0].PropertyName}" />
<DataTemplate />
To bind to just one item from a collection, you can use the following syntax:
{Binding Items[0]}
Or to bind to a property of a single item from the collection:
{Binding Items[0].Property}
You can find out more about property path syntax from the Binding.Path Property page at MSDN... from the linked page:
• Indexers of a property can be specified within square brackets following the property name where the indexer is applied. For instance, the clause Path=ShoppingCart[0] sets the binding to the index that corresponds to how your property's internal indexing handles the literal string "0". Multiple indexers are also supported.
Try this
<ContentControl Content="{Binding YourCollection[0]}">
<ContentControl.ContentTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"></TextBlock>
</DataTemplate>
</ContentControl.ContentTemplate>
</ContentControl>
Ok, late to the party but I thought I'd share my 2 cents anyway: I'd better go with a dumber (XAML-)view and a view-model closer to your presentation needs.
Translated: instead of mapping your existing view-model (or raw data) and its collection of items directly to the view, I suggest to map that to an appropriate view-model showing something like a YourItemViewModel FirstItem property and a bool HasMore property. That second view-model would be easily unit-testable to make sure it behaves propertly, and would be easily mapped to a view with less logic, so to avoid possible hard-to-test problems in view.
{Binding Items[0].SomeProperty}
{Binding [0].SomeProperty}
{Path=/SomeProperty}

Current binding value

I'm writing markup extension. I have XAML like this
<TextBlock Text="{ui:Test SomeInfo}" />
and TestExtension with constructor taking one string argument. I'm getting "SomeInfo" string so everything is find. Now I want to nest extensions and write something like
<TextBlock Text="{ui:Test {Binding PropName}}" />
and it does not work as is. I had to add constructor which takes one argument of System.Windows.Data.Binding type.
Now I need to know
How should I retrieve a current value from the Binding object?
When should I do this? Should I subscribe to changes some way or ask for that value every time in ProvideValue method?
Update1 PropName should be resolved against DataContext of TextBlock.
Update2 Just found related question: How do I resolve the value of a databinding?
Bindings like this will not work because your MarkupExtension has no DataContext and it does not appear in the visual tree and i do not think you are supposed to interact with binding objects directly. Do you really need this extension? Maybe you could make do with the binding alone and a converter?
If not you could create a dedicated class which has bindable properties (by inheriting from DependencyObject), this however would still not give you a DataContext or namescope needed for ElementName or a visual tree needed for RelativeSource, so the only way to make a binding work in that situation is by using a Source (e.g. set it to a StaticResource). This is hardly ideal.
Also note that if you do not directly set a binding the ProvideValue method will only be called once, this means that even if you have a binding in your extension it may not prove very useful (with some exceptions, e.g. when returning complex content, like e.g. an ItemsControl which uses the binding, but you set the extension on TextBlock.Text which is just a string), so i really doubt that you want to use a MarkupExtension like this if the value should change dynamically based on the binding. As noted earlier: Consider converters or MultiBindings for various values instead.

Databinding to functions in dynamically-loaded plugins

I have several MenuItems whose Commands are bound to my ViewModel. Until today, all of them execute properly.
Now I have added a MenuItem whose ItemsSource is bound to an ObservableCollection. The point of this MenuItem is to enumerate a list of plugins so that the name of all plugins show up. Then when the user clicks on a plugin name, it should call a function to display properties for audio filters.
In my current implementation, which doesn't work, I tried to databind like this:
<MenuItem Header="Filters" ItemsSource="{Binding FilterPluginNames}">
<MenuItem.ItemContainerStyle>
<Style>
<Setter Property="MenuItem.Command" Value="{Binding ShowFilterDialogCommand}" />
</Style>
</MenuItem.ItemContainerStyle>
</MenuItem>
The problem is that I get a BindingExpression path error because it's trying to use a String as the MenuItem's DataContext.
This leads me to believe that the DataContext for a MenuItem's MenuItems is automatically set to type of objects in the ItemsSource. Is this true?
If I need to change the DataContext, then I'd like to change it to the ViewModel that handles all of my other Commands. But if I do that, how in the world am I able to tell which plugin I want to display filter properties for? I'd need to pass in a CommandParameter at the very least, but binding this value to the filter name isn't my most favorite option. Are there any other ways to do this?
If the DataContext is indeed automatically set to the object type in the ObservableCollection, then I'd rather just call my interface method ShowFilterProperties() directly. I bet that I can't do this without Command binding. If that is the case, how do you all deal with this sort of application? Do you make all of the plugins expose a command handler, which will then show the dialog?
EDIT -- I modified my code to change the ObservableCollection type, and sure enough, WPF wants to databind to the type T. So I guess one option is to have the plugin expose the ICommand, but I don't know if this is a weird approach or not?
EDIT -- ok, I just learned something new. Interfaces can't have fields, so is it not possible to databind with plugins, period?
You are likely not quite binding like you think you are. You might want to just put some diagnostics on your bindings and see what object they are binding to. Here is a good link for debugging bindings:
http://www.beacosta.com/blog/?p=52
Here's a sample:
<Window …
xmlns:diagnostics="clr-namespace:System.Diagnostics;assembly=WindowsBase"
/>
<TextBlock Text="{Binding Path=Caption, diagnostics:PresentationTraceSources.TraceLevel=High}" … />
I think your approach is correct... it probably just needs to be debugged a little.

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

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