WPF // MahApps.Metro // Caliburn.Micro // Flyout // HeaderedContentControl - wpf

Since a change in MahApps.Metro 1.5.0 the base element of a Flyout was changed from ContentControl to HeaderContentControl. Now the MVVM approach with Caliburn.Micro and this suggestion doesn't work anymore.
Has anybody else tried to solve this issue in a nice MVVM way?

While I haven't tried it myself but since the new Flyout control is now based on HeaderedContentControl it would be a simple logic choice to attempt to do this instead of the previous, which was based on ContentControl. Looks like the advantages of this change were the elimination of a couple of dependency properties...
<controls:FlyoutsControl.ItemTemplate>
<DataTemplate>
<HeaderedContentControl cal:View.Model="{Binding}" />
</DataTemplate>
</controls:FlyoutsControl.ItemTemplate>
The other thing that might come out of this that you create a Caliburn.micro convention to actually bind correctly to that HeaderedContentControl which wouldn't be all that different from the ContentControl variant was, by default in CM already. What is odd is that this HeaderedContentControl is derived from ContentControl in theory it should have been found correctly. Another thing to think about is this actually might also be related to Visual Tree where CM can't see it till it's in the tree, therefore can't bind it.
Content Control convention in CM source as a reference.

I've added posted a work around on GitHub.
It appears there's something going on with setting the ItemTemplate of the FlyoutsControl.

Related

Q: Update viewmodel property from a listview binded textbox

i've got a textbox which text is binded to a listview selecteditem as follows:
<TextBox x:Name="txtAdditional" Width="300" Text="{Binding ElementName=lstPersons, Path=SelectedItem.Additional, Mode=OneWay}" />
Now i like to implement a mechanism to add new items to the listview using this textbox to get the actual data. So i would like to bind the text of the textbox to a property of the viewmodel so it can be processed by a command.
So it the textboxes text has to be binded to the listviews selecteditem and additionally to a property of my viewmodel.
I've searched around and found some approaches but i can't help to think that there should be some simpler mechanism to archive this goal.
What I found by now:
Using MultiBindung with some kind of ValueConverter? So it seems to me that this is primary for displaying and not for updating a viewmodels property.
The use of some selfdefined custom control?
The use of an BindingProxy with in- and out-dependencyproperties like in Impossible WPF Part 1: Binding Properties?
Is there another, simpler solution to this or would i have to use one of those above?
And if one should use one of those approaches, which one whould you choose?
I can't help but thinking that this issue hasn't been given some thoughts already, using an mvvm pattern?! ;-)
yes thanks to the hint from BionicCode.
We, or better I should have to think the MVVM concept out. Of course no - or at least as little code behind as possible.
I added the property "selectedPerson" to my viewmodel and bound the SelectedItem of the listview to this property. So the object related properties were at hand directly through the "selected" object in my viewmodel and there was no need anymore to access the textbox content at all.
Thanks to BionicCode for the hint!

Using a UserControl type vs a control's concrete type

Okay, I understand what a UserControl is and how they can be shared across multiple Windows/Views to share functionality, etc. Though, what is the benefit of using a UserControl type? It seems a lot cleaner if you were to use the root control instead of wrapping it inside a UserControl.
Example:
<UserControl>
<Grid>
//...
<Grid/>
</UserControl>
vs.
<Grid>
//...
</Grid>
Using the root control also has the benefit if reducing the VisualTree.
UserControl has some properties it inherits from ContentControl, like ContentTemplate, ContentTemplateSelector, some other stuff. If you don't need those, you can create a user control, change the outermost element to Grid and change its base class to Grid in the .xaml.cs, and it'll compile. At least with the trivial example I just tried, it works fine.
However, unless you've identified some concrete problem being created by UserControl in your application, I can't see any reason to go to the trouble. But go ahead, if you like doing things that way.

Add view directly to xaml with Caliburn Micro

I'm still experimenting a bit with Caliburn Micro and I can't seem to find a way to directly add a view to a xaml without adding another ContentControl with a property in the viewmodel behind it.
I can place this: <views:TheView ... /> in the xaml but then it can't find the target actions so it seems it doesn't find the viewmodel behind the view.
Is it possible to directly declare a view in a xaml without a ContentControl, and how?
You will have to tell Caliburn to bind the view model to a user control.
In the definition of "TheView" are you able to add the following line to the UserControl element:
cal:Bind.Model="TheViewModel"
So it will look similar to:
<UserControl x:Class="Example.Views.TheView"
cal:Bind.Model="Example.ViewModels.TheViewModel" ...
While looking into this I did find this answer to another StackOverflow question:
Does Caliburn.Micro play nicely with user controls?

Get XAML View element without breaking MVVM

I need a reference to a Visual (one element of a XAML View Window) in my ViewModel to work with VisualTreeHelper methods like VisualTreeHelper.GetDescendantBounds(Visual reference) but I do not want to break MVVM rules and just name the viewport3d and provide it as a reference when instancing my ViewModel.
Currently I am binding the geometry as content like this to my ViewModel:
<Viewport3D>
<ModelVisual3D Content="{Binding SceneContent.Content}"/>
</Viewport3D>
But I do not see the MVVM possibility to get the containing ModelVisual3D into my ViewModel. Is there a standard (may be data-binding) approach to this in MVVM applications?
Using MVVM, we don't 'get view elements'. If you need to do something with a UI element, then that has nothing to do with MVVM. If you need to use the VisualTreeHelper.GetDescendantBounds method, then once again, that has absolutely nothing to do with MVVM... why do so many people claim to use MVVM, but know nothing about it?
Therefore, your question is invalid. It is entirely appropriate in situations like these for you to use the code behind. In fact, this is a perfect example of when we should use the code behind when following the MVVM methodology. If it is only UI related, then it has no purpose being in a view model, so simply don't put it there.
Please read the answer to the What are MVVM limitations? question to get some further insight into MVVM.

How do you navigate a complex Visual Tree in order to re-bind an existing element?

In the above image, child is a ContentPresenter. Its Content is a ViewModel. However, its ContentTemplate is null.
In my XAML, I have a TabControl with the following structure:
<local:SuperTabControlEx DataContext="{Binding WorkSpaceListViewModel}"
x:Name="superTabControl1" CloseButtonVisibility="Visible" TabStyle="OneNote2007" ClipToBounds="False" ContentInnerBorderBrush="Red" FontSize="24" >
<local:SuperTabControlEx.ItemsSource>
<Binding Path="WorkSpaceViewModels" />
</local:SuperTabControlEx.ItemsSource>
<TabControl.Template>
<ControlTemplate
TargetType="TabControl">
<DockPanel>
<TabPanel
DockPanel.Dock="Top"
IsItemsHost="True" />
<Grid
DockPanel.Dock="Bottom"
x:Name="PART_ItemsHolder" />
</DockPanel>
<!-- no content presenter -->
</ControlTemplate>
</TabControl.Template>
<TabControl.Resources>
<DataTemplate DataType="{x:Type vm:WorkSpaceViewModel}">
....
WorkSpaceViewModels is an ObservableCollection of WorkSpaceViewModel. This code uses the code and technique from Keeping the WPF Tab Control from destroying its children.
The correct DataTemplate - shown above in the TabControl.Resource - appears to be rendering my ViewModel for two Tabs.
However, my basic question is, how is my view getting hooked up to my WorkSpaceViewModel, yet, the ContentTemplate on the ContentPresenter is null? My requirement is to access a visual component from the ViewModel because a setting for the view is becoming unbound from its property in the ViewModel upon certain user actions, and I need to rebind it.
The DataTemplate is "implicitly" defined. The ContentPresenter will first use it's ContentTemplate/Selector, if any is defined. If not, then it will search for a DataTemplate resource without an explicit x:Key and whose DataType matches the type of it's Content.
This is discussed here and here.
The View Model shouldn't really know about it's associated View. It sounds like there is something wrong with your Bindings, as in general you should not have to "rebind" them. Either way, an attached behavior would be a good way to accomplish that.
I think the full answer to this question entails DrWPF's full series ItemsControl: A to Z. However, I believe the gist lies in where the visual elements get stored when a DataTemplate is "inflated" to display the data item it has been linked to by the framework.
In the section Introduction to Control Templates of "ItemsControl: 'L' is for Lookless", DrWPF explains that "We’ve already learned that a DataTemplate is used to declare the visual representation of a data item that appears within an application’s logical tree. In ‘P’ is for Panel, we learned that an ItemsPanelTemplate is used to declare the items host used within an ItemsControl."
For my issue, I still have not successfully navigated the visual tree in order to get a reference to my splitter item. This is my best attempt so far:
// w1 is a Window
SuperTabControlEx stc = w1.FindName("superTabControl1") as SuperTabControlEx;
//SuperTabItem sti = (SuperTabItem)(stc.ItemContainerGenerator.ContainerFromItem(stc.Items.CurrentItem));
ContentPresenter myContentPresenter = FindVisualChild<ContentPresenter>(stc);
//ContentPresenter myContentPresenter = FindVisualChild<ContentPresenter>(sti);
DataTemplate myDataTemplate = myContentPresenter.ContentTemplate;
The above code is an attempt to implement the techniques shown on the msdn web site. However, when I apply it to my code, everything looks good, except myDataTemplate comes back null. As you can see, I attempted the same technique on SuperTabControlEx and SuperTabItem, derived from TabControl and TabItem, respectively. As described in my original post, and evident in the XAML snippet, the SuperTabControlEx also implements code from Keeping the WPF Tab Control from destroying its children.
At this point, perhaps more than anything else, I think this is an exercise in navigating the Visual Tree. I am going to modify the title of the question to reflect my new conceptions of the issue.

Resources