Add behavior to RadioButton in ItemsControl (Windows 8 Search) - xaml

I'm implementing the search contract (results page) of a Windows 8 application. I've designed everything to follow MVVM. With that, I'm trying to wire up a command to the 'filtersItemsControl' that is provided in the search contract template for Windows 8.
<ItemsControl
x:Name="filtersItemsControl"
Canvas.ZIndex="1"
ItemsSource="{Binding Source={StaticResource filtersViewSource}}"
Visibility="{Binding ShowFilters, Converter={StaticResource BooleanToVisibilityConverter}}"
Margin="120,-3,120,30">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<RadioButton
GroupName="Filters"
IsChecked="{Binding Active, Mode=TwoWay}"
common:CheckedCommandBehavior.Command="{Binding RelativeSource={RelativeSource Self}, Path=FilterChangedCommand}"
Style="{StaticResource TextRadioButtonStyle}">
<TextBlock Text="{Binding Description}" Margin="3,-7,3,10" Style="{StaticResource GroupHeaderTextStyle}" />
</RadioButton>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
The code above is my attempt to hook into 'FilterChangedCommand' which is a property of the ViewModel. The ViewModel also contains a list of properties that the ItemsControl is bound to (filtersViewSource). I think my issue is that I'm trying to bind the Command of the RadioButton to a property of filtersViewSource (which obviously does not exist) vs. the ViewModel.
So with that, I THINK the question here is basically, what binding expression can I used on the above RadioButton such that it will reference the ViewModel property.

FiltersViewSource should a property in viewmodel of some type, say "Foo". In that case, radio button will get datacontext of type Foo. So the property "FilterChangedCommand" should be in Foo class.

Related

Windows 8.1 how to automatically wrap grid items?

I'm building a universal app and my Win8.1 app has to show a grid of items. Normally the grid consists of 3 columns, but on smaller screens I want the items to wrap so that there are only 2 columns (or even 1). This is my code:
<GridView ItemsSource="{Binding Regions}" IsItemClickEnabled="True">
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid Orientation="Horizontal" MaximumRowsOrColumns="3" MinWidth="400" />
</ItemsPanelTemplate>
</GridView.ItemsPanel>
<GridView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="10">
<Image Source="{Binding Code, Converter={StaticResource FlagIconConverter}, ConverterParameter='/Assets/Icons/Flags/{0}.png'}" Width="30" />
<TextBlock Text="{Binding NativeName}" Style="{StaticResource BodyTextBlockStyle}" Margin="10,0,0,10" VerticalAlignment="Center" />
</StackPanel>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
Whenever I make the app smaller, the items do not automatically wrap. I tried solving this by changing the MaximumRowsOrColumns property with a VisualStateManager but that didn't work because it couldn't access my WrapGrid for some reason. Changing the property from code-behind didn't work either, because again it couldn't access the WrapGrid.
I tried this with both WrapGrid and ItemsWrapGrid (what is the difference anyway?) and ListView and GridView. No difference there.
Does anyone know how to accomplish this?
You shouldn't need to do anything. It should wrap based on the available client area. The only thing I can think of that would not make it wrap is that you put your <GridView> inside a fixed width container or a container that is size Auto in which you don't update the Observable Collection to notify the Grid to redraw/update itself.
For example this will not wrap.
<Grid Width="1000">
<GridView x:Name="myGridView" IsItemClickEnabled="True">
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid Orientation="Horizontal" MaximumRowsOrColumns="5"/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
<GridView.ItemTemplate>
<!-- DATATEMPLATE -->
</GridView.ItemTemplate>
</GridView>
</Grid>
However get rid of that Width=1000 and it will wrap.
Example output 3 different sizes

Binding from multi object in to one value in XAML

I have a ListView which have a DataTemplate like this:
<DataTemplate x:Key="FilterDataTemplate">
<StackPanel Orientation="Horizontal" Background="White" Height="50" HorizontalAlignment="Left">
<ComboBox x:Name="TermsItemComboBox" Width="160"
ItemsSource="{Binding ItemList}" Tag="{Binding}"
DisplayMemberPath="Key" SelectionChanged="AddTermsItem_SelectionChanged"
Background="#FFD1D1D1" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" />
<TextBox x:Name="TermsInputTxt1" Text="{Binding FilterText, Mode=TwoWay}"
BorderBrush="#FF727272" Background="#FFD1D1D1" HorizontalAlignment="Left"
Width="200" FontSize="16" VerticalAlignment="Center"
Visibility="{Binding IsTxtForm, Converter={StaticResource BooleanToVisibilityConverter}}"
Height="45"/>
<TextBox x:Name="TermsInputTxt2" Text="{Binding FilterText, Mode=TwoWay}"
BorderBrush="#FF727272" Background="#FFD1D1D1" HorizontalAlignment="Left"
Width="200" FontSize="16" VerticalAlignment="Center"
Visibility="{Binding IsTxtForm, Converter={StaticResource BooleanToVisibilityConverter}}"
Height="45"/>
<Button x:Name="TrashBtn" HorizontalAlignment="Left" VerticalAlignment="Stretch"
BorderBrush="#FF575757" Foreground="#FF494949" BorderThickness="2" Tapped="TrashBtn_Tapped"
Style="{StaticResource DiscardAppBarButtonStyle}" Height="45" Width="55"
RenderTransformOrigin="0.5,0.5">
<Button.RenderTransform>
<CompositeTransform ScaleX="-1" />
</Button.RenderTransform>
</Button>
</StackPanel>
It's have a combobox and two TextBox. At default, the combobox don's show anything, just a blank item, I want when user type some text to the TermsInputTxt1 or TermsInputTxt2, the combobox will select the first item.
I try to bind the selectedindex of combobox with the lenght of those two textbox with a converter but look like XAML doesn't support multi binding like that.
Any suggest? Thank you!
So, this is a bit of a difficult situation. You have a couple of ways of going about it:
Bind the TermsInputTxt1 and TermsInputTxt2 to the ViewModel, with the Setter on the ViewModel controlling an ObservableCollection, adding and removing items as they get set in the property.
Create a Model for each entry with a Value field (string) and bind the Terms... to accessors in the ViewModel. Then, the ComboBox items will automatically change.
I suggest doing the first one. You'll have to have a SelectedItem/SelectedIndex property in the ViewModel which the ComboBox will bind to. You may also want to change the method by which the binding on the TextBoxs are updated, either so that they are updated immediately (lots of processing) or after it loses focus (less processing, but won't update the UI immediately).

WP8 - access datacontext of parent

How can I access the datacontext of the parent element in windows phone 8?
AncestorType is not available in WP8.
<ItemsControl x:Name="Elements" ItemsSource="{Binding MyList}" Grid.Row="2" Grid.Column="3">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<toolkit:WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="e" Width="100" Height="100" Command="{Binding MyCommand" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
"MyCommand" is defined outside of "MyList". So how can I access from my button to the root datacontext (DataContext = MyClass).
MyCommand is defined in the MyClass class.
Thanks in advance.
You could use an ElementName Binding instead. If your root grid (the one directly inside your page) is called LayoutRoot:
<Button Command="{Binding DataContext.MyCommand, ElementName=LayoutRoot}" />

Howto correctly bind RibbonGalleryCategory to a collection

I'm using Microsoft.Windows.Controls.Ribbon.
I want to have a dynamic combobox with picture buttons in my ribbon.
If I do this directly in xaml, I get what I want:
<ribbon:RibbonComboBox
SelectionBoxWidth="62"
VerticalAlignment="Center"
>
<ribbon:RibbonGallery SelectedValue="0"
SelectedValuePath="Content"
MaxColumnCount="1">
<ribbon:RibbonGalleryCategory>
<ribbon:RibbonButton Label="Histo" HorizontalContentAlignment="Stretch"
Command="{Binding NewHistogrammCommand}"
SmallImageSource="/Test;component/Resourcen/Histogramm32.png"
LargeImageSource="/Test;component/Resourcen/Histogramm32.png" />
<ribbon:RibbonButton Label="3D" HorizontalContentAlignment="Stretch"
Command="{Binding NewDreiDCommand}"
SmallImageSource="/Test;component/Resourcen/DreiD32.png"
LargeImageSource="/Test;component/Resourcen/DreiD32.png" />
</ribbon:RibbonGalleryCategory>
</ribbon:RibbonGallery>
</ribbon:RibbonComboBox>
But if I try to do this via binding to a collection this way:
<ribbon:RibbonComboBox
SelectionBoxWidth="62"
VerticalAlignment="Center"
IsEditable="True" >
<ribbon:RibbonGallery
MaxColumnCount="1">
<ribbon:RibbonGalleryCategory ItemsSource="{Binding LayoutContentTypeList, ElementName=mainWindow}">
<ribbon:RibbonGalleryCategory.ItemTemplate>
<DataTemplate>
<ribbon:RibbonButton Label="{Binding Header}" HorizontalContentAlignment="Stretch"
Command="{Binding Command}"
CommandParameter="{Binding CommandParameter}"
SmallImageSource="{Binding ImageSource}"
LargeImageSource="{Binding ImageSource}" />
</DataTemplate>
</ribbon:RibbonGalleryCategory.ItemTemplate>
</ribbon:RibbonGalleryCategory>
</ribbon:RibbonGallery>
</ribbon:RibbonComboBox>
I get
System.Windows.Data Error: 40 : BindingExpression path error: 'IsDropDownOpen' property not found on 'object' ''ContentPresenter' (Name='')'. BindingExpression:Path=IsDropDownOpen; DataItem='ContentPresenter' (Name=''); target element is 'RibbonButton' (Name=''); target property is 'NoTarget' (type 'Object')
The buttons work correctly, but how can I resolve this binding error?
I'm guessing that you've found a solution for your problem, but for other people coming across this post, looking for an answer, you can find a complete solution that you can download and examine at your leisure in the How do I add Galleries to my Ribbon? post at 'The official blog of the Windows Presentation Foundation Team'. The basic idea is as follows.
Whatever object that you set as the RibbonGallery.DataContext should have a collection property to bind to the RibbonGalleryCategory.ItemsSource property. The objects in that collection should have properties containing the values that you want to appear in the gallery items. Declare a HierarchicalDataTemplate for the RibbonGallery.CategoryTemplate to bind your properties. Here is an example from the linked post:
<Ribbon:RibbonGallery DataContext="{x:Static data:WordModel.StylesParagraphGalleryData}"
ItemsSource="{Binding CategoryDataCollection}"
ScrollViewer.VerticalScrollBarVisibility="Hidden">
<Ribbon:RibbonGallery.CategoryTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding GalleryItemDataCollection}">
<Border Background="LightGray">
<TextBlock Text="{Binding}" FontWeight="Bold" />
</Border>
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="Images\Paragraph_32x32.png" />
<TextBlock Margin="10,0,0,0" Text="{Binding}" />
</StackPanel>
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</Ribbon:RibbonGallery.CategoryTemplate>
</Ribbon:RibbonGallery>

eventtocommand for dynamically created controls silverlight mvvm light

I want to add a trigger to a dynamically created control but I couldn't. The event doesn't fire. This is my code.
<sdk:HierarchicalDataTemplate x:Key="NameTemplate"
ItemsSource="{Binding LstRs}"
ItemTemplate="{StaticResource RsTemplate}">
<TextBlock Text="{Binding Nom}" FontWeight="Bold" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseEnter">
<gs:EventToCommand Command="{Binding Path=StateCommand}"
CommandParameter="{Binding Text, ElementName=TextBoxSearch, Mode=OneWay}"
MustToggleIsEnabledValue="True"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBlock>
</sdk:HierarchicalDataTemplate>
and the command is implemented in the view model.
IMHO, the most common error in such a case is that the command was not created - i.e. StateCommand == null - when the data is bound. Make sure you created the command in the constructor of you view-model.