UWP Bind to ObservableCollection declaratively - xaml

I have a simple UWP page; there is a public ObservableCollection in the page code-behind:
public ObservableCollection<Book> MyObservableColl{ get; } = new ObservableCollection<Book>();
(note the collection consists of a single item)
I would like to bind to the collection; here is what I tried:
<StackPanel x:Name="stackPanel"
Grid.Row="2"
Margin="50"
DataContext="{x:Bind MyObservableColl, Mode=OneWay}">
<TextBox x:Name="txtTitle"
TextWrapping="Wrap"
Text="{x:Bind Title, Mode=OneWay}" />
</StackPanel>
The visual studio designer complains "the property Title was not found".
I appreciate any help to bind my text boxes to the Observable Collection.

the property Title was not found
txtTitle TextBox can't access Book item where in the MyObservableColl collection directly, you need place txtTitle under items control's ItemTemplate.
For example
<ListView ItemsSource="{x:Bind MyObservableColl, Mode=OneWay}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:Book">
<StackPanel>
<TextBox Text="{x:Bind Title}" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
For more info please refer to listview document.
Update
For single item please refer to this xaml
<StackPanel
x:Name="stackPanel"
Grid.Row="2"
Margin="50"
DataContext="{x:Bind MyObservableColl[0], Mode=OneWay}">
<TextBox Text="{Binding Title}"/>
</StackPanel>

Related

UWP XAMl ListView Item Template MVVM Events

If I want to implement the MVVM patern. What is the correct procedure for implementing a event such as DoubletTapped on TextBlock inside a Datatemplate of a ListView.ItemTemplate?
<ListView.ItemTemplate>
<DataTemplate x:DataType="classes:Person">
<TextBlock
DoubleTapped="{x:Bind}"//what goes here to call a method on the ViewModel
Foreground="Green"
Text="{x:Bind Name}" />
</DataTemplate>
</ListView.ItemTemplate>
Please modify your TextBlock Xaml as below:
<TextBlock Foreground="Green" Text="{x:Bind Name}" >
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="DoubleTapped">
<core:InvokeCommandAction Command="{Binding ElementName=RootPage, Path=DataContext.YourCommandMethod}"/>
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</TextBlock>
RootPage is the name of Root Element, which in my case is a Page.

How to find LongListMuliselector inside another ListBox

I need to find the LongListMultiSelector inside ListBox .
<ListBox x:Name="ListBoxName" Width="400">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<Bewise:ExpanderControl x:Name="bewiseControl" HeaderText="{Binding Title, Mode=OneWay}" Width="400" >
<Bewise:ExpanderControl.ContentArea>
<toolkit:LongListMultiSelector ItemsSource="{Binding LstProdcuts}" x:Name="LongList">
<toolkit:LongListMultiSelector.ItemTemplate >
<DataTemplate>
<StackPanel >
<TextBlock Text="{Binding Title}" />
</StackPanel>
</DataTemplate>
</toolkit:LongListMultiSelector.ItemTemplate>
</toolkit:LongListMultiSelector>
</Bewise:ExpanderControl.ContentArea>
</Bewise:ExpanderControl>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
i need to access LongList inside ListBoxName.I needed this LongList to get the selected item and itemSource or to add item to the selecteditem of the list
You could use the VisualTreeHelper class in order to access elements within.
Example!

How to change the parent of DataContext in xaml in Windows phone 8.1

I have this xaml in windows phone 8.1.
My page data context is binded to a ViewModel, i.e. VM.
And My listView is binded to Items of ViewModel.
And the text in each list view item is binded to Text of Items of ViewModel.
<Page DataContext="{Binding VM}">
<ListView ItemsSource="{Binding Items}">
<ListView.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding Text}"/>
<TextBox Text="{Binding soemthing in VM}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Page>
My question is how can I change the parent datacontext of my 2nd TextBox so that I can bind something in my ViewModel (not my ViewModel.Items)?
Thank you.
If you don't mind Element Binding,
<ListView ItemsSource="{Binding Items}">
<ListView.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding Text}"/>
<!-- Bind the DataContext directly to the whatever element you like, in this case the page, then the Text Binding is basically the DataContext.VM_Property -->
<TextBlock Text="{Binding DataContext.VM_Property}" DataContext="{Binding ElementName=page}" ></TextBlock>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>

Using different databinding sources within ListBox and ContextMenus

Here is the XAML:
<ListBox ItemsSource="{Binding Documents}" BorderBrush="{x:Null}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Title}" FontSize="12" FontWeight="Bold" />
<TextBlock Text="{Binding ID}" FontSize="10" FontStyle="Italic" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ContextMenu>
<ContextMenu ItemsSource="{Binding CategoryList}">
<ContextMenu.ItemTemplate>
<DataTemplate>
<MenuItem Command="{Binding AddDocumentToCategoryContextMenuCommand}" Header="{Binding Category.Name}" />
</DataTemplate>
</ContextMenu.ItemTemplate>
</ContextMenu>
</ListBox.ContextMenu>
</ListBox>
Ok so the ListBox's ItemSource is bound to the Documents collection in the VM and properly renders the Titles and IDs
The Context Menu's ItemSource is bound to the CategoryList collection in the VM and properly renders the list of categories.
The problem I have is with the Command Binding:
Command="{Binding AddDocumentToCategoryContextMenuCommand}"
Since the ItemSource for the ContextMenu is already set, it tries to get the AddDocumentToCategoryContextMenuCommand from CategoryList. Obviously the command is not there, it is a member of the VM.
I do not want any references to the VMs or Models in the XAML. Everything is constructed using Unity and VM-View is associated in App.xaml:
<Application.Resources>
<DataTemplate DataType="{x:Type vms:FeedViewModel}">
<views:FeedView/>
</DataTemplate>
<DataTemplate DataType="{x:Type vms:DocumentsViewModel}">
<views:DocumentsView/>
</DataTemplate>
<DataTemplate DataType="{x:Type vms:ManagementViewModel}">
<views:ManagementView/>
</DataTemplate>
<DataTemplate DataType="{x:Type dev:DevelopmentViewModel}">
<dev:DevelopmentView />
</DataTemplate>
</Application.Resources>
How can I databind to a member of the VM from within the ContextItem.
Thanks.
UPDATED edit #1 starts Here
Here is the updated xaml (but still not working but some insight gained):
<ListBox ItemsSource="{Binding Documents}" x:Name="Results" BorderBrush="{x:Null}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Title}" FontSize="12" FontWeight="Bold" />
<TextBlock Text="{Binding ID}" FontSize="10" FontStyle="Italic" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ContextMenu>
<ContextMenu ItemsSource="{Binding CategoryList}">
<ContextMenu.ItemTemplate>
<DataTemplate>
<MenuItem Command="{Binding ElementName=Results, Path=DataContext.AddDocumentToCategoryContextMenuCommand}" Header="{Binding Category.Name}" />
</DataTemplate>
</ContextMenu.ItemTemplate>
</ContextMenu>
</ListBox.ContextMenu>
</ListBox>
I have this example working for a simple example that does not use a ContextMenu. It appears that the ContextMenu (even though attached to the ListBox) is not part of the user control visual tree. The binding always comes back null / not found. I think the ContextMenu, because it is a floating "window" is constructed in its own tree and therefore cannot find the ListBox call "Results" in order to access the ListBox's DataContext.
Any thoughts on this? Any recommendations on how deal with?
Edit #2 Starts Here
In case you are are wondering, figured out the answer to the binding question:
This binding works:
Command="{Binding RelativeSource={RelativeSource AncestorType=ContextMenu}, Path=PlacementTarget.DataContext.AddDocumentToCategoryContextMenuCommand}
Hope this helps others with the same question.
One last update for completeness.
In order for the command to know which context menu item was clicked on, I had to change the xaml slightly (silly oversight):
<ListBox.ContextMenu>
<ContextMenu x:Name="Context" ItemsSource="{Binding CategoryList}">
<ContextMenu.ItemTemplate>
<DataTemplate>
<MenuItem Command="{Binding RelativeSource={RelativeSource AncestorType=ContextMenu}, Path=PlacementTarget.DataContext.AddDocumentToCategoryContextMenuCommand}"
CommandParameter="{Binding Category.ID}"
Header="{Binding Category.Name}" />
</DataTemplate>
</ContextMenu.ItemTemplate>
</ContextMenu>
</ListBox.ContextMenu>
Again, hope this helps others.
Use the ElementName property of the binding to specify that. You'd end up with something like this:
Command="{Binding ElementName=ViewModelObject
Path=AddDocumentToCategoryContextMenuCommand}"

Access property of DataContext in ItemTemplate

My datacontext has two properties: Items which is a collection and DetailsVisiblity which is enum of type Visiblity.
On the page I have a Listbox with ItemsSource="{Binding Entries}". Inside the DataTemplate, I can bind stuff to properties of Items, but how do I get access to DetailsVisiblity which is a property of DataContext?
DataContext has two properties: ObservableCollection<Item> Entries, and Visibility DetailsVisiblity. Item class has two properties: Title and Details.
Here is the view. How do I bind Visiblity of the second TextBlock to DetailsVisiblity property?
<ListBox ItemsSource="{Binding Items}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Title}" />
<TextBlock Text="{Binding Details}" Visibility="{Binding ???}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
You could name the ListBox and in the Binding you reference it with ElementName, and in Path you use DataContext.DetailsVisibility
<ListBox x:Name="listBox" ItemsSource="{Binding Items}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Title}" />
<TextBlock Text="{Binding Details}"
Visibility="{Binding ElementName=listBox,
Path=DataContext.DetailsVisibilty}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>