I have WinRT application with following GridView:
<GridView x:Name="RouteGrid"
ItemsSource="{Binding Routes}"
SelectedItem="{Binding SelectedRoute,
UpdateSourceTrigger=PropertyChanged,
Mode=TwoWay}"
SelectionMode="Single">
<GridView.ItemTemplate>
<DataTemplate>
<Grid Width="300" Margin="4">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock FontWeight="Bold" Text="{Binding TermText}" />
<TextBlock Grid.Column="1" Text="{Binding ConnectionObjects.Count}" />
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
I want to show a button instead of the second textblock when ever the item is selected because I want to allow my users to navigate to another view when they've selected.
I would like to do it in pure XAML because that is for me the cleanest way but I have no idea how to bind to the IsSelected property of the GridViewItem.
In WPF I would bind the Visibility property of the TextBlock and the button with a BooleanToVisibilityConverter and RelativeSource to the AncestorType GridViewItem and its property but that's not working because WinRT does not know AncestorType :(
Thanks for help.
Related
I am building a Custom Control for Windows Phone 8.1. But the stackpanel is not scrolling down. StackPanel contains one ListView which shouws a TextBlock & another StackPanel which houses a Toggle Button.
<StackPanel Orientation="Vertical" >
<ListView Grid.Row="0" Background="RoyalBlue">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<TextBlock Text="Some Text" Foreground="Black" FontSize="20" TextAlignment="Center" ></TextBlock>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<StackPanel Grid.Row="2" HorizontalAlignment="Stretch" Background="Red" Orientation="Horizontal">
<Grid HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<ToggleButton Grid.Column="0" Content="Toggle Me" />
</Grid>
</StackPanel>
</StackPanel>
Stackpanel doesn't provide any scrolling.
You can wrap it into a ScrollViewer.
Also: listView already provides Scrolling.
But: The ListView inside stackpanel will pick up all your manipulation events. Also, a ListView inside a Stackpanel will have infinite heigt and therefore loose it's virtualization capabilities.
If you just want to have content above and/below the ListView, maybe use its Header/Footer properties.
Add ScrollViewer over the StackPanel and it will make it scrollable.
For Example:
<ScrollViewer Margin="12">
<StackPanel>
<TextBlock Text="content1" FontSize="48" />
<TextBlock Text="content1" FontSize="48" />
</StackPanel>
</ScrollViewer>
I have a dock panel to the left of my screen which contains a listbox. The listbox is populated with custom items, defined in another class. To the right of my listbox i have a gridsplitter.
When i click and drag my gridsplitter, the listbox gets resized as expected, howvever the items inside do not.
I would like the items inside to resize accordingly so i can use textrimming when the control would be cut off.
I currently have:
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150" MaxWidth="500" MinWidth="100"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<toolkit:DockPanel HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0,0,9,0">
<Button toolkit:DockPanel.Dock="Top" Height="30" Content="Create" Visibility="{Binding Path=IsVisible, Mode=TwoWay}" Command="{Binding Path=Create, Mode=TwoWay}" />
<ScrollViewer HorizontalAlignment="Stretch" VerticalAlignment="Stretch" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Hidden">
<ListBox HorizontalAlignment="Stretch" ItemContainerStyle="{StaticResource ItemContainerStyle}" ItemsSource="{Binding Path=ViewModel, Mode=TwoWay}" SelectedItem="{Binding Path=Selected, Mode=TwoWay}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical" HorizontalAlignment="Stretch">
<ContentControl HorizontalAlignment="Stretch">
<myNamespace:MycustomControl HorizontalAlignment="Stretch" DataContext="{Binding}" Height="40"/>
</ContentControl>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</ScrollViewer>
</toolkit:DockPanel>
<sdk:GridSplitter Width="10" HorizontalAlignment="Right" Grid.Row="1" Style="{StaticResource VerticalGridSplitterStyle}" />
Also within my custom item class, everything is defined HorizontalAlignment = Stretch and has no fixed width set.
Edit: Also i have tried binding my custom item's width to my listbox width with no luck.
It turned out that the horizontal scroll bar was causing the issue (even though it wasn't visible)
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
Solved my issue
I'm new to WinRT so apologies if this is a silly question. I've created the following ListView:
<ListView x:Name="MyListView1"
Grid.Row="1"
Margin="120,300,0,0"
Width="500"
HorizontalAlignment="Left">
<ListViewItem Background="DodgerBlue">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200" />
<ColumnDefinition Width="300" />
</Grid.ColumnDefinitions>
<TextBlock Text="hardcoded value 1" Grid.Column="0"></TextBlock>
<TextBlock Text="hardcoded value 2" Grid.Column="1"></TextBlock>
</Grid>
</ListViewItem>
</ListView>
This looks the way I want it to look, and if you click an item it will select the whole row. However, if I move this into a DataTemplate it doesn't look the same, and you can no longer click the whole row. (If I add an ItemContainerStyle with the target type ListViewItem and set the background to yellow, it will fill it up so it's the same size as the hardcoded ListItem, but you can only click the yellow outline to select it.) This is the code:
<ListView x:Name="MyListView2"
ItemTemplate="{StaticResource MyTemplate}"
ItemsSource="{Binding MyData}"
Grid.Row="1"
Margin="120,0,0,0"
Width="500"
HorizontalAlignment="Left">
</ListView>
And in StandardStyles.xaml:
<DataTemplate x:Key="MyTemplate">
<ListViewItem Background="DodgerBlue">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200" />
<ColumnDefinition Width="300" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding MyDataOne}" Grid.Column="0"></TextBlock>
<TextBlock Text="{Binding MyDataTwo}" Grid.Column="1"></TextBlock>
</Grid>
</ListViewItem>
</DataTemplate>
I don't understand why they don't look/work the same - shouldn't it get populated with the exact same code when you bind it? What do I need to do to make it work?
The problem there is the way you created the datatemplate. Remember that ListViewItem is a wrapper added to any object that needs to be displayed in the list, so when you create a datatemplate that contains a listviewitem you are basically wrapping the object twice. All you need to do is remove the listviewitem element from the datatemplate
<DataTemplate x:Key="MyTemplate">
<Grid Background="DodgerBlue">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200" />
<ColumnDefinition Width="300" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding MyDataOne}" Grid.Column="0"></TextBlock>
<TextBlock Text="{Binding MyDataTwo}" Grid.Column="1"></TextBlock>
</Grid></DataTemplate>
I have a Windows Phone 8 app using XAML/C#. My app has an ItemsControl that relies on a data template. My DataTemplate looks like the following:
<DataTemplate x:Key="myTemplate">
<Grid Margin="0,0,0,8">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid VerticalAlignment="Center">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Text="{Binding DisplayName}" TextWrapping="NoWrap" Style="{StaticResource PhoneTextLargeStyle}" TextTrimming="WordEllipsis" >
<toolkit:ContextMenuService.ContextMenu>
<toolkit:ContextMenu>
<toolkit:MenuItem x:Name="customerMenuItem" Foreground="White" Header="View Customer Profile" Click="customerMenuItem_Click" Tag="{Binding Path=CustomerName}" />
</toolkit:ContextMenu>
</toolkit:ContextMenuService.ContextMenu>
</TextBlock>
<TextBlock Text="{Binding Summary}" TextWrapping="NoWrap" Grid.Row="1" Style="{StaticResource PhoneTextSmallStyle}" />
</Grid>
<StackPanel Orientation="Horizontal" Grid.Column="1"><!-- Stuff here --></StackPanel>
</Grid>
</DataTemplate>
This DataTemplate is referenced in the main part of my XAML as shown here:
<Grid x:Name="ContentPanel" Grid.Row="1" Grid.ColumnSpan="2" Margin="12,0,12,0">
<ScrollViewer>
<ItemsControl x:Name="myItemsControl" ItemTemplate="{StaticResource myTemplate}" ItemsSource="{Binding Customers}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</ScrollViewer>
</Grid>
Please note, the "toolkit" namespace comes from clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit. When I hold my finger (or mouse) on the TextBlock, a context menu appears. However, I never see the words "View Customer Profile". I just see a block box that represents the context menu itself. I know that the item is there though. I know because the customerMenuItem_Click event successfully fires. I have a MessageBox in there that shows the value of the Tag. That value is always correct. For some reason though the menu item text is not appearing. What am I doing wrong?
You put Foreground = "White". Context menu is on white background. That is why you don't see your menu item.
I finally got my pivot control to work using MVVM in a wp8 app but I still have a question in regards to binding as thought as it works, and I could accept it as is, I'm not happy with the outcome and I'm trying to understand why this is happening. My DataContext, MainViewModel, contains multiple other ViewModels.
Scenario 1:
If I define the DataContext in the Grid (layout), and I assign the itemsSource for the pivot headers to QuickSearchTabs ViewModel and this get built ok but the listbox I have defined inside the pivotitem doesn't which is assigned the QuickSearchButtons ViewModel doesn't get built. Here is the xaml code:
<Grid x:Name="LayoutRoot" Background="Transparent" DataContext="{StaticResource MainViewModel}" >
<phone:Pivot x:Name="Pivot" ItemsSource="{Binding QuickSearchTabs}" FontSize="{StaticResource PhoneFontSizeSmall}" SelectedIndex="{Binding SelectedSearchTabIndex, Mode=TwoWay}">
<phone:Pivot.Title>
<TextBlock Text="My Search Options" />
</phone:Pivot.Title>
<phone:Pivot.HeaderTemplate>
<DataTemplate>
<ContentControl Content="{Binding Name}" />
</DataTemplate>
</phone:Pivot.HeaderTemplate>
<phone:Pivot.ItemTemplate>
<DataTemplate>
<ListBox ItemsSource="{Binding QuickSearchButtons}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Button Content="{Binding Name}" Grid.Row="0">
</Button>
<TextBlock Text="{Binding Description}" Grid.Row="1">
</TextBlock>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DataTemplate>
</phone:Pivot.ItemTemplate>
</phone:Pivot>
</Grid>
Scenario 2:
If I define the DataContext in the Grid (layout) and define the same DataContext within the listbox tags, it will build my header and my listbox BUT it will call my viewModel which is assigned to the ItemsSource of the listbox, multiple times. To be exact, it will call it the same number of time as the number of pivots I have. Here is the xaml code:
<Grid x:Name="LayoutRoot" Background="Transparent" DataContext="{StaticResource CriteriaViewModel}" >
<phone:Pivot x:Name="Pivot" ItemsSource="{Binding QuickSearchTabs}" SelectedIndex="{Binding SelectedSearchTabIndex, Mode=TwoWay}" >
<phone:Pivot.Title>
<TextBlock Text="My Search Options" />
</phone:Pivot.Title>
<phone:Pivot.HeaderTemplate>
<DataTemplate>
<ContentControl Content="{Binding Name}"/>
</DataTemplate>
</phone:Pivot.HeaderTemplate>
<phone:Pivot.ItemTemplate>
<DataTemplate>
<ListBox ItemsSource="{Binding QuickSearchButtons}" DataContext="{StaticResource CriteriaViewModel}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Button Content="{Binding Name}" Grid.Row="0">
</Button>
<TextBlock Text="{Binding Description}" Grid.Row="1">
</TextBlock>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DataTemplate>
</phone:Pivot.ItemTemplate>
</phone:Pivot>
</Grid>
As mentioned, this works, and it's not affecting me in anyway as the correct data is always displayed.
I can somehow see what's happening but why on earth would the ItemsSource be set for each of the defined pivot headers. Surely, the only important one is the one coming into visibility!
I don't know if Pivots are suppose to be used the way I'm using them. It seems, from what I've seen so far that normally a view is assigned to each PivotItem. This is not how I want my solution to work!
I just want numerous headers which are used to groups things in a specific manner and whatever is displayed under each is build dynamically but on the same view i.e. list of buttons and label.
Any ideas on how I could get scenario 1) to work and if I'm stuck with scenario 2, how to stop it from being triggered based on the number of pivot header items?
Thanks.
Problem solved!
The QuickSearchTabs was an observable collection of QuickSearchTab when it should have been an observable collection of ViewModel i.e. QuickSearchTabViewModel and within this viewModel, it will load the observable collection of relevant QuickSearchButtons for each of the tab.
Having a QuickSearchTabViewModel provides more flexibility and it will allow access to the current tab (header), and other relevant properties including everything maintain within each of these tabs such as, in my case the buttons.
Hope this helps.