Binding acting strange with ItemPanel and ok without - silverlight

The following code on displays the {Binding text} and the dependency property for Sprites does not run the propertyvaluechanged for text runs but not for sprites.
<ItemsControl x:Name="AnswerListBox" ItemsSource="{Binding Answers}" ScrollViewer.VerticalScrollBarVisibility="Disabled" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:spriteRadioButton Text="{Binding text}" Sprites="{Binding Path=DataContext.UISprites, ElementName=questionField}" GroupName="{Binding Path=DataContext.QuestionTitle, ElementName=questionField}" IsChecked="{Binding selected}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<toolkit:WrapPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
if i don't use an itemspaneltemplate then the properties work as expected.

At the moment you're using the default "OneWay" binding mechanism. This means that your object can update the UI but the UI cannot update the object.
Your binding should use "TwoWay" binding in order to allow the UI to notify the object of changes:
<DataTemplate>
<local:spriteRadioButton Text="{Binding text,Mode=TwoWay}" Sprites="{Binding Path=DataContext.UISprites, ElementName=questionField,Mode=TwoWay}" GroupName="{Binding Path=DataContext.QuestionTitle, ElementName=questionField,Mode=TwoWay}" IsChecked="{Binding selected,Mode=TwoWay}" />
</DataTemplate>
Keep in mind, these changes will update your Answers object. If you want to change the Answers object itself this too will need to be marked as TwoWay binding as well.

Related

Bound String List displays containing class name not the string

My Problem is the following:
I have a class which has a ObservableCollection of strings, which gets populated by the selected children.
Those are supposed to be listed in a ListBox.
But the strings aren't listed, rather the object type in FilterList is shown.
<ListBox Grid.Row="2" Grid.Column="0"
ItemsSource="{Binding FilterList}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel IsItemsHost="True"
Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding ListOfActiveFilters}">
<!--<ContentPresenter Content="{Binding ListOfActiveFilters.}"/>-->
<TextBlock Text="{Binding}" />
</HierarchicalDataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Filter List contains the classes which have ListOfActiveFilters as a Property.
I thought that it would work the way I showed it, but it doesn't.
Since that is also the way I saw others do it.
If I were to use a Class with a single string Property as the type of the Collection instead of the Collection of strings I have right now, I think it would work.
I just don't really see the point in creating a class which holds a string property just so that I can bind the ContentPresenter or TextBox to that property.
What am I doing wrong? I am rather new to the topic.
One single ListBox will only be able to display the filters in one single ListOfActiveFilters collection. You could use nested ItemsControls to display them all:
<ItemsControl ItemsSource="{Binding FilterList}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<ListBox ItemsSource="{Binding ListOfActiveFilters}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
The other option is to modify your data model and put all strings in a single collection. You could then bind the ItemsSource property of the ListBox directly to this one. But a ListBox itself has no concept of hierarhical data.

WPF checkbox affecting multiple items in collection

I am binding a nested object to a set of controls:
Parameter.ParameterOptionGroup.ParameterOptions
binded to:
<ItemsControl ItemsSource="{Binding Parameters}">
<ItemsControl ItemSource="{Binding ParameterOptionGroup.ParameterOption}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding State}"></CheckBox>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ItemsControl>
Oddly, whenever I check some of the checkboxes, it triggers other checkboxes. I noticed that this happens when the checkbox's source object has the same Id. Truth to be told, a ParameterOption can be assigned as a member of any ParameterOptionGroup.
Is there a way to avoid this without changing my schema?

MahApps.Metro: WindowCommands ItemsSource binding

I am trying to bind a collection of items to the windowcommands of metrowindow. Below is the xaml snippet.
<metro:MetroWindow.WindowCommands>
<metro:WindowCommands ItemsSource="{Binding WindowCommands}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="{Binding DisplayName}"
Command="{Binding Callback}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</metro:WindowCommands>
</metro:MetroWindow.WindowCommands>
But it does not display the DisplayName property, but the type name of the bounded datatype. How can I achive the intended behaviour?
Works if you add the template as a resource to the MetroWindow. For this to work you will need to create a WindowCommandViewModel that has Label and Callback properties.
<metro:MetroWindow.Resources>
<DataTemplate DataType="{x:Type viewModels:WindowCommandViewModel}">
<Button Content="{Binding DisplayName}"
Command="{Binding Callback}"/>
</DataTemplate>
</metro:MetroWindow.Resources>

Hide the group header of a listview by binding in Windows Store App

I'm trying to remove group headers for groups where the header title is empty. But I can not make the binding in HeaderContainerStyle work. Neither can I set visibility on the TextBlock in TemplateHeader 'cause that will leave a small space and not be completely invisible.
This is my XAML:
<Page.Resources>
<CollectionViewSource
x:Name="MenuItemsGrouped"
IsSourceGrouped="True"
Source="{Binding MenuItems}" />
</Page.Resources>
<ListView Grid.Row="1" Margin="0"
ItemsSource="{Binding Source={StaticResource MenuItemsGrouped}}"
IsSynchronizedWithCurrentItem="False"
SelectionMode="Single"
SelectedItem="{Binding SelectedItem, Mode=TwoWay}">
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding Title}" />
</DataTemplate>
</GroupStyle.HeaderTemplate>
<GroupStyle.HeaderContainerStyle>
<Style TargetType="ListViewHeaderItem">
<Setter Property="Visibility" Value="{Binding GroupHeaderVisibility}"></Setter>
</Style>
</GroupStyle.HeaderContainerStyle>
</GroupStyle>
</ListView.GroupStyle>
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0" Orientation="Horizontal">
<TextBlock Text="{Binding Title}" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Does anyone have a solution - and maybe a reason the binding won't work?
EDIT:
Ok, it's is actually a limitation in Windows Store Apps and earlier Silverlight apps:
Windows Presentation Foundation (WPF) and Microsoft Silverlight
supported the ability to use a Binding expression to supply the Value
for a Setter in a Style. The Windows Runtime doesn't support a Binding
usage for Setter.Value (the Binding won't evaluate and the Setter has
no effect, you won't get errors, but you won't get the desired result
either). When you convert XAML styles from WPF or Silverlight XAML,
replace any Binding expression usages with strings or objects that set
values, or refactor the values as shared StaticResource values rather
than Binding-obtained values.
from http://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.setter
And see also Silverlight: How to use a binding in setter for a style (or an equivalent work around)
Just try to bind the Visibility of the root element of HeaderTemplate.
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding Title}" Visibility = "{Binding GroupHeaderVisibility}" />
</DataTemplate>
</GroupStyle.HeaderTemplate>
It should work.Good luck!
[Edit]
I have figured out a solution, it's not very elegant, but it works. Here are the steps:
Add this xaml code to your ListView:
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
2.Get a copy of ContainerStyle of GroupStyle(Right click the Listview on the design surface.Select: "Edit GroupStyle"->"ContainerStyle"). Then remove this line from the attributes of ContentControl:
Margin = "4"
3.Apply the above ContainerStyle to your listview. It should work.
NOTE: Step 1 is necessary, because ContainerStyle is no longer honored on Windows 8.1 when ItemsPanel is an ItemsStackPanel(which is the default).
http://msdn.microsoft.com/en-us/library/windows/apps/dn263110.aspx
You are binding to the Visibility property which is of type Visibility. My guess is that the GroupHasHeader property is a boolean; you should use a Boolean to visibility converter.

Access property of DataContext inside ItemTemplate

I have a really nasty problem with bindings. I know that there are other topics regarding binding itmes inside itemtemplate to datacontext of an object outside the template. However, this just won't work, i.e. the first textblock display 'Test' as desired whereas the same textbox inside the itemtemplate shows nothing.
<TextBlock Text="{Binding DataContext.Test, ElementName=myList}"/>
<ItemsControl x:Name="myList" ItemsSource="{Binding AllItems}"
Margin="0,0,0,0" VerticalAlignment="Top" HorizontalAlignment="Center">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<toolkit:WrapPanel Orientation="Horizontal"
ItemHeight="170" ItemWidth="140"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<Image x:Name="{Binding KeyName}"
Source="{Binding ImagePath}"
Width="128"
Height="128">
</Image>
<TextBlock Text="{Binding DataContext.Test, ElementName=myList}"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I would appreciate some help here folks as this is really a problem for me.
Inside the itemtemplate, the binding is initialized to the context of the current item in AllItems.
Update
Outside of the ItemTemplateyour bindings are relative to the DataContext of the page.**
Once inside an ItemTemplate then bindings are limited to the scope of the item specifically being evaluated at that time.
So, if we assume the following (based on the code in your question):
<ItemsControl x:Name="myList" ItemsSource="{Binding AllItems}" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock x:Name="tb1"
Text="{Binding DataContext.Test, ElementName=myList}"/>
<TextBlock x:Name="tb2" Text="{Binding KeyName}"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
tb1 cannot access the DataContext object directly.
tb2 cann access KeyName - assuming that whatever object AllItems is an IEnumerable of contains a property with that name.
As I understand it, inside an itemtemplate, the item past from the enumeration controls the binding source and this can't be overridden (by setting ElementName or otherwise).
If you need the value from Test in every object in your enumeration then you'll need to add it as a property of the object in the enumeration.
I'm sure someone more knowledgeable than me could explain why this is or give a better explanation but that's the gist of it.
** Assuming no other nesting of ItemsControls (or equivalent)

Resources