Hello I am looking for a solution to get a SelectedItem from my TreeView. The XAML has a ViewModel through which I would like to access the SelectedItem. Since XAML always generates the code in the CodeBehind cs file for me and I can't find a way to get the data in the ViewModel, I'm asking you now.
Related
The UWP XAML ItemsControl is the basis for many complicated XAML classes, like ListView and GridView.
The documentation Item containers and templates describes 2 key parts of these controls:
Data template
Control template
These parts combine to create the final view:
Container controls (such as ListViewItem and GridViewItem) consist of two important parts that combine to create the final visuals shown for an item: the data template and the control template.
In practice, developers specify the data template by specifying a DataTemplate in ListView.ItemTemplate (or GridView.), and they can customize the control template by providing a Style (TargetType="ListViewItem") to ListView.ItemContainerStyle.
Developers can also customize the ListView.ItemsPanel (which is an ItemsStackPanel by default), and the default Template for the ListView.ItemContainerStyle contains a ListViewItemPresenter. The documentation for Item containers and templates mentions these, too.
That raises the question:
When I add a ListView (or GridView or any ItemsControl) to my code, what am I actually adding? What can I customize? How is my data displayed?
As far as I can determine, the ListView looks something like:
ListView
Renders its Template which somehow renders:
ItemsPanel
Renders its ItemsPanelTemplate which is:
ItemsStackPanel
Renders, for each item:
ListViewItem
Renders its Template, which is:
ListViewItemPresenter
Somehow renders:
ListView.ItemTemplate
But this is unclear to me.
Disclaimer: I work for Microsoft.
you can customize anything in xaml
under the hood, both ListView and GridView can be created by ItemsControl, but their default template have some customization built-in already.
if you want to understand when to use which, here is a page:
https://learn.microsoft.com/en-us/windows/uwp/design/controls-and-patterns/lists
your data will be set to the ItemsSource if using binding, for example
<ListView
ItemsSource="{Binding Source={StaticResource itemsViewSource}}"
>...
or you can set directly.
from your question, it sounds like you may not have understood the basis, so maybe reading this series will help you:
http://drwpf.com/blog/itemscontrol-a-to-z/
it's for wpf, but the fundamental is the same, you can apply it to UWP as well.
I need help with a change of perspective.
I got stuck trying to approach UWP in a way I used to do in WPF regarding a MVVM pattern for managing UserControls dynamically.
I naturally tried to perform the same pattern in UWP but got stuck on various things like UWP not supporting 'x:Type' ...
Situation is; time to rethink this approach and look for a new direction. Seems I'm forced to abandon to use implicit binding in a similar fashion to the WPF pattern, using the Content property of a ContentPresenter and a VM property 'of type Object', which maintain a selected ViewModel. It was a simple and clean approach for matching up the correct View automagically with the VM set in ActiveViewModel.
the below was such a simple way of managing many views all over the place, odd MS not fixing this? But, back to the big Q: what now in UWP!?
<ContentPresenter Content="{Binding ActiveViewModel}">
<ContentPresenter.Resources>
<DataTemplate DataType="{x:Type local:OneViewModel}">
<local:OneView />
</DataTemplate>
<DataTemplate DataType="{x:Type local:TwoViewModel}">
<local:TwoView />
</DataTemplate>
</ContentPresenter.Resources>
</ContentPresenter>
What Shall I do instead of this!? Anyone found a new efficient way of doing it? I got stuck in my stubborn mind and need someone to kick my butt so I go forward. Getting to old to change, but due to this profession it seems I constantly have to. :)
Looking at the DataTemplate documentation, there's a paragraph explaining the situation which you are trying to figure out.
For advanced data binding scenarios, you might want to have properties
of the data determine which template should produce their UI
representations. For this scenario, you can use a DataTemplateSelector
and set properties such as ItemTemplateSelector to assign it to a data
view. A DataTemplateSelector is a logic class you write yourself,
which has a method that returns exactly one DataTemplate to the
binding engine based on your own logic interacting with your data. For
more info, see Data binding in depth.
Here, you have an example on how you can select distinct DataTemplate for items in a control such as a ListView based on defined conditions.
Your situation is a bit different from the one described above, but the solution should be within what is explained above.
Create a class which derives from DataTemplateSelector, and override the SelectTemplateCore methods exposed by it, where you define the logic of what DataTemplate should be selected for the specific presented object.
This Derived class should expose properties of type DataTemplate, which identify each single DataTemplate template object, you pretend to be able to choose from.
Just as in the example, you are probably better of by defining the DataTemplate resources on an higher level object, such as the Page itself.
Instantiate your DataTemplateSelector Derived class in XAML as a resource and set each of the properties exposed above of type DataTemplate to the analogous DataTemplate static resource.
Utilize the ContentTemplateSelector dependency property, by setting it your custom DataTemplateSelector.
With this logic, it should be possible to have your ContentPresenter decide correctly between which DataTemplate it should choose from, based on your required UI logic.
I'm trying the MVVM pattern and I've run into a problem.
Here's how I instantiate my model:
<common:LayoutAwarePage
...
...(omitted boiler plate generated lines here)
...
...
mc:Ignorable="d">
<common:LayoutAwarePage.DataContext>
<local:TextGameClientModel x:Name="textGameClientModel"/>
</common:LayoutAwarePage.DataContext>
But when I try to use it, I get a NullReferenceException because this.textGameClientModel is NULL:
public MainPage()
{
this.InitializeComponent();
this.textGameClientModel.runsPublished += textGameClientModel_runsPublished;
}
I've also tried the same line in the Page's OnNavigateTo handler, and also in the OnLoaded handler, but with the same result.
Where is the right place to hook up my event handler?
(Please don't let my code-behind in an MVVM project distract you from the question. My use of a RichTextBox has forced me to color outside the lines a little.)
I actually wrote an answer about the WPF Creation Steps fairly recently, however that's not the problem in this case.
In this case, you are setting the DataContext in your XAML, however that's not the same as setting the textGameClientModel property
You need to do something like this to set the property equal to your DataContext first
this.textGameClientModel = this.DataContext as GameClientModel;
or simply cast your DataContext as your class to setup the event
((GameClientModel)this.DataContext).runsPublished += textGameClientModel_runsPublished;
As a side note, I never recommend hardcoding the DataContext into a UserControl like you have. By doing so, you are preventing any other DataContext from getting passed to the UserControl, which kind of defeats one of the biggest advantages of WPF/MVVM, which is having separate UI and data layers.
I have a GridView as my zoomed out view in a SemanticZoom control. This GridView uses a custom DataTemplateSelector as the ItemTemplateSelector. It shows an item for each content group that my app shows.
The template is different depending on whether the group is empty or not. This works fine on load, but it doesn't update when a group becomes empty or stops being empty.
I've found that the ItemTemplateSelector is only run when the page is first shown. How can I force the DataTemplateSelector get run again.
The WPF questions on this topic all suggest triggers, but these aren't available in WinRT XAML.
I've found an answer to a similar WPF question that answers this in a way that works in WinRT:
https://stackoverflow.com/a/11327087/31569
Basically you set the ItemTemplateSelector to null and then set it again. Like this:
var templateSelector = MyGroupView.ItemTemplateSelector;
MyGroupView.ItemTemplateSelector = null;
MyGroupView.ItemTemplateSelector = templateSelector;
This works, but happy to be told if there is a better way to do this.
I find it easier to just just remove the item in need updating from the collection and adding it back. This forces the GridView or ListView to apply the template. This is easy to do in MVVM world.
var itemToReload; //The object who's template needs updating
var reloadIndex = this.SomeCollection.IndexOf(itemToReload);
this.SomeCollection.Remove(itemToReload);
this.SomeCollection.Insert(reloadIndex, itemToReload);
One thing to note, is that if the item is a "Selected" item, you'll need to reapply that selection.
We're trying to do some localization in our Silverlight app. Normal localization is no problem: we write the bindings in XAML and our textblock items show the correct text.
For items in datatemplates or for enums, we are experiencing some issues. We are binding a property (string) to the content of a button in the datatemplate. We have our 7 values shown on 7 buttons. But now we try to get those values from the dictionary (resx) and we cannot get a decent binding working. This is how we try now:
Content="{Binding Source={StaticResource ApplicationResources}, Path=?}"
At the question mark is where we used to place our static key: ItemType. But now we need to get the value from a collection bound to the parent (listbox) of the button.
Is there any syntax that can make this binding work?
We also doing something similar with enums binding to comboboxes. Any ideas on how we can get that localization to work?
Thanks in advance