WPF - how to bind to source in different page? - wpf

Could anyone answer a really frustrating newbie question please?! I've been hunting for an answer for a few days & have found answers to similar questions posed, but nothing that exactly solves my issue.
I'm trying to bind a textbox to the currently selected item in a listview (which itself is bound to an Observablecollection of objects, not sure if this matters).
The listview is in RecentEntities.xaml & the textbox is in Relationship.xaml, both of which are positioned on the Main Window from within Maincontrol.xaml. So they're in the same namespace but they're in different pages so using ElementName doesn't work as this just seems to look within the current page.
The issue I'm having is when trying to define the source of the textbox binding in Relationship.xaml, how do I reference the selected listview item in RecentEntities.xaml? I wondered about using RelativeSource, but this seems to only let you navigate up the tree to an ancestor of the current control. Because of how MainControl is set up, I would need to travel up to the parent of the textbox, then to a sibling of the parent then down to a child of a child of it in order to get to the listview!
I've explored (possibly not in enough depth) other options like resources, data context, including header files and have read something about Merged Resource Dictionaries but to be honest the more possibilities I explore, the more confused I'm getting about what I need to be doing.
Is this really as complicated as it seems?! Any pointers or help would be brilliant, thanks for taking the time to answer :) I haven't posted on here before, so if you need any code snippets please let me know.

Can you create a ViewModel that both Views will use? Have the selected item in your listview bind to a property in the ViewModel and have the textbox bind to the same property. As long as both views reference the same instance of the viewmodel, it should work.

With two XAML files you will have to use the model or viewmodel (depending on your choice of architecture) for synchronization.
For the listview you can use the SelectedValue to bind to a property, use Mode=OneWayToSource for this binding since you just want to update the property, not change the selection in the listview itself.

Related

Mvvm light wpf navigation

What I want to achieve. A navigation service for MVVM Light WPF where I can easily say NavigateTo(View URI or ViewModel and a string name of the framework element that should present the View or ViewModel).
I first tried the View First approach from here.
https://stackoverflow.com/a/28968560/5272185
Problems I found with it was that the Frame frameworkelement seems to run sandboxed, and even though I set the view's datacontext to bind to a viewmodel retrieved from my viewmodellocator I seem to get a different instance inside the Frame. Also styles seem not to be inherit down into the Frame and the MVVM Light Messenger's messages do not seem to bubble up from the View shown inside a Frame.
Also the code to find the Frame element failes if the Frame is located within a ViewBox. I have no clue why but if I just remove the ViewBox it finds it correctly.
I ignored the ViewBox issue (removed the ViewBox) and changed the NavigationService to store ViewModelBase types instead of URI, and I changed the code to find a FrameworkElement of type ContentControl instead of Frame, set the ContentControl's content instead of a Frame's source. This so I should not run into the sandbox problem. This worked, but I now have no good way of switching to a detail view (using the same ViewModel as datacontext for multiple views).
Questions
When using a ViewModel first NavigationService as explained above, is there an easy way to show a detail view (sharing a ViewModel) without code duplication?
In case of a View first navigationservice exactly like the code in the link. Is there a way to make the Frame inherit the correct datacontext and styles (not running sandboxed at all)?
Can someone explain why the VisualTreeHelper code in the provided link does not find a framework element if the element is inside a ViewBox?
I should also mention that I have tried the approach to make a CurrentVM property and CurrentDetailMode property on the ViewModel and bind a ContentControl's content to the CurrentVM property and used DataTemplates with DataTriggers (bind to CurrentDetailMode) to set the corresponding View(s) to the ViewModels. According to this post.
https://rachel53461.wordpress.com/2011/12/18/navigation-with-mvvm-2/
It works well and supports detail views. My goal with the navigationservice is that I want to add all views or viewmodels to the service in one place. Not having to create the CurrentVM and CurrentDetailMode properties on every ViewModel that should be able to show different content / views. And I would prefer an easier solution than manually setting up Datatemplates with special DataTriggers for supporting "Detail" views. Also the navigation service discussed has a history queue so one can go back.
I managed to solve / answer my own questions
Just create a dumb ViewModel class for the Detail view, provide it with the (Main)ViewModel instance and make that ViewModel instance a property so you can bind to it. Done! Easy after all, and with Dependency injection it can become a breath.
See this link page.DataContext not inherited from parent Frame?
I solved this one and tracked it in the following separate question. See answer here
WPF ViewBox blocks VisualTreeHelper search

Filter Telerik WPF RadGridView from ViewModel in MVVM app

I am going crazy trying to figure out how to manipulate telerik RadGridView for WPF's column filtering from my ViewModel. I thought I might be able to bind the value of a FilterDescriptor to a ViewModel property, but I get
Cannot find governing FrameworkElement or FrameworkContentElement for target element
<telerik:CompositeFilterDescriptor>
<telerik:FilterDescriptor Member="Foo.SomeProperty" Operator="IsContainedIn" Value="{Binding SelectedThings}" />
</telerik:CompositeFilterDescriptor>
where Foo.SomeProperty is a VM property bound to a grid column and SelectedThings is a VM property containing a stringified array of unique values to filter against.
GridView is bound to a QueryableCollectionView.
I want the filtering to work at runtime, based upon some custom logic in the VM - ex. user clicks some button and the VM restricts distinct values of one of the columns.
This shouldn't be so hard. I must be approaching this wrong. I've been pooring over other stackoverflow questions but haven't found a solution that works yet. Any suggestions would be appreciated.
UPDATE
I would still like to achieve this with a completely MVVM approach, but for the time being I've decided to stop going nuts over it and resolve the issue in the following way.
ViewModel's ObservableCollection which is bound to a list of checkboxes representing some filtering criteria are updated by the user through the GUI.
Upon that property change the ViewModel sends a message via Messenger (MVVMLIGHT) which in the codebehind has registered to receive. The message includes the filtering criteria information.
The codebehind receives it and applies it directly to the GridView.
What's nice about this is it avoids having to wire up any DependencyProperties or other event handlers and allows the VM to remain ignorant of the View implementation. It's simple and it works.
Yes, there's a little code behind now, but until I can find some better info on how to solve this problem purely through MVVM binding, this is a workable solution.
Wish I'd done this at 9 AM yesterday instead of banging my head against the wall all day long reading Telerik's crappy documentation and hunting for examples of how to do it "the right way". Meh.

WPF: TemplateSelectors for different GridViews

Currently I have a UserControl that displays collections of data in the same layout. So one control could be instanced with a collection of ObjectA and another of ObjectB. I then use TemplateSelectors to choose the right DataTemplates.
Later on we thought we'd set the List as a GridView to show more information in the list itself. However each type of object has different properties and the columns may have different names and not the same quantity. I realized then that the columns and such where not set in the ItemTemplate but at the GridView itself and ListView of course has no templateSelector for itself.
I wasn't sure how to do it but several ways came into mind.
1) There is some kind of TemplateSelector property I'm not aware off.
2) I CAN set it somehow at the ItemTemplateSelector only don't know how.
3) I could do the GridView dynamically (could be difficult and wan't to avoid).
Any good way to do this, tutorials or similiar I could use?
EDIT:
As I have learned a little bit more about ListView and it's view property I'm pretty sure I could define the gridview in a staticResource. Still I would love a ViewSelector or something similar. I guess this was of course not intended as the the item could be dynamic while the Collection isn't.
But I'm thinking about cases where there could exist more types of view then gridview ( iconview or something else) and the user could switch between them it would have to be implemented in some way.
The solution I see know is using a trigger and basing it on the first item in the collection but I'm not liking that too much.
Have you looked at the AutoGeneratingColumns property of the Grid?
http://msdn.microsoft.com/en-us/library/system.windows.controls.datagrid.autogeneratingcolumn(v=vs.95).aspx

WPF: Activate Trigger when a MVVM bound property changes

somehow I am going in circles here. Please forgive me if the answer to this question is obvious.
I want to react to changed properties in the ViewModel in the View. When the properties (bool) change the View should start an animation (BeginStoryBoard).
Actually in my application there are 4 of these properties each with its own name in the VM and two desired animations each (hide/show) for the respective 4 container view elements.
When setting these Triggers (tried DataTrigger/Trigger/EventTrigger) directly in the respective container elements (all of them of custom type SizerControl derived from ContentConrol) wpf gave me errors suggesting using a style. When setting a style directly in the container elements I got: "The tag 'Style.Triggers' does not exist in XML namespace ..."
But when using a style in a global ResourceDictionary I am at a loss how to bind to the 4 containersto get the "input" value for the trigger.
Do you have a suggestion how to solve this from an architecture pov? Maybe I am already down too far the wrong path to see the obvious solution.
Thanks a bunch,
Hinnerk
You can do this with a DataTrigger and a StoryBoard.
MSDN has a full sample describing the process, with code, documented in How to: Trigger an Animation When Data Changes.

How to display in each ListBoxItem textblocks with binding to a filelds of a different tables

Greetings to all and sorry for my English!
I have a ListBox, it's ItemsSource = myClientsList.DefaultView. The Items of ListBox have a template (ControlTemplate), that is defined in a in a separate resource file.
Every Item contains a little TextBlock's, Text -property of each have a binding to fields of my Object myClientsList.
I need to add in a this item template more TexBlock's and each of them must have binding to fields of another my class myOrdersList. - (So I wish to view on each line of ListBox information from different tables of my database - this is a question).
Problem in that that ListBox's ItemsSource have a link to object myClientsList and I cann't set myOrderList to ItemSource of same ListBox. So i must find a way to specify TextBlock.DataContext wich inside ControlTemplate or how it's possible to solve this problem in another way?
p.s. I'm a new in .Net and WPF and probably have a mistakes in my explanation - sorry for it.
It sounds like you have a DataGrid type of display and want to add more columns in order to display the order information for a given client. If this is the case, you are going to have to do a couple of things. First, you will need to create a composite object that stores information for both entities into a single object (so each row of your control has all the data it needs to display). Secondly, I would recommend using an actual DataGrid control to display rows instead of templating a ListBoxItem. The ListView with a GridView built into the framework isn't great, so I would recommend the WPFToolkit's DataGrid for a free option.
There are two issues here, if I've understood the question: how do you create a single collection containing both Clients and Orders, and how do you display Clients and Orders in different ways within the same ListBox?
Regarding the first, you can do this using a CompositeCollection.
Regarding the second, define two DataTemplates instead of a ControlTemplate. As the key of each DataTemplate, use the type of the object it is going to present e.g.
<DataTemplate x:Key="{x:Type local:Client}">
Alternatively, use ItemsControl.ItemTemplateSelector to explicitly point at different DataTemplates depending on the type of item. Ot if you really have to use ControlTemplates, check out ItemsControl.ItemContainerStyleSelector.

Resources