Caliburn Micro not support cal:View.Context at design-time? - caliburn.micro

Create window:
<Window
d:DataContext="{d:DesignInstance Type=MyType, IsDesignTimeCreatable=True}"
cal:Bind.AtDesignTime="True">
<ContentControl cal:View.Model="{Binding Model}" cal:View.Context="ViewContext1"/>
</Window>
Create view for view-model named [Root namespace].Model.ViewContext1.
At design time see "Can't find view for view-model".
When run - is all right.

When using Caliburn.Micro in ViewModel first approach, and binding contextual content inside a view to same model (initial ViewModel), make sure to set View.Context before setting View.Model.
You will want to swap them around in this case like so:
<ContentControl cal:View.Context="ViewContext1" cal:View.Model="{Binding Model}" />

Related

Prism Partial views xamarin forms

I am using Prism to build xamarin forms apps.
I have never used Partial Views and cannot find any examples out there.
Can somebody point me to an example,so that I can see if fits what I am trying to achieve?
many thanks
From the Docs:
The concept of a Partial View is to support a custom layout which may
be reused across multiple pages, and eliminate ViewModel logic
duplication by allowing that custom layout to rely on its own
ViewModel. To use a Partial View you must set the
ViewModelLocator.AutowirePartialView property with a reference to the
containing page as shown here. You should not set the
ViewModelLocator.AutowireViewModel property on the Partial View unless
you are explicitly opting out as setting this property to true
directly may result in the ViewModel being incorrectly set.
Example:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:AwesomeApp.Views"
xmlns:prism="clr-namespace:Prism.Ioc;assembly=Prism.Forms"
xmlns:mvvm="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
x:Name="self"
x:Class="AwesomeApp.Views.ViewA">
<StackLayout>
<local:AwesomeView mvvm:ViewModelLocator.AutowirePartialView="{x:Reference self}" />
<Entry Text="{Binding SomeValue" />
</StackLayout>
</ContentPage>

How to pass data to a viewmodel in Caliburn.Micro

This is probably a very simple question, but at this time I have myself so confused I can't see the answer. Simply put, I have a window that contains a content control. I'm using Caliburn.Micro's conventions to "locate" the view.
The window looks like this:
<Window x:Class="Views.MainWindowView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<TextBox/>
<ContentControl x:Name="MyViewModel" Height="Auto" Background="Blue"/>
</Grid>
</Window>
The view itself is successfully found, and the screen displays as I expected. However, MyViewModel needs to make a service call to get information based on what is typed into the text box.
So, what I can't seem to figure out is how one would pass that information from the text box to the view model. I've thought of several options, but they all seem to be too much work which makes me think that I'm missing something simple.
Thanks a lot
Like you said there are a number of things you can do:
You could expose a property on MyViewModel and set it within
MainWindowView.
You could use the EventAgregator, publish an event from the
MainWindowView and subscribe to that event from MyViewModel.
Using MEF you could inject a shared resource between the two
ViewModels, set it in MainWindowViewModel, and be able to access it
from MyViewModel.

silverlight - binding to two objects

I want to create a user control, which can be bound to some data given from outside the control (requirement A), and some XAML properties must be bound to properties of the control itself (requirement B).
Let's say that I have a data class named StudentData and a control named StudentControl. I'm using this control inside a DataGrid. I put the StudentControl in the grid with a DataGridTemplateColumn. I somehow bind the StudentData in the current cell to the control. This is requirement A. This StudentControl wants to specify if some of the controls inside it are editable or not. The best way to do this is exposing a property, like StudentControl.AreSomeControlsEditable. Then I can bind the IsEnabled property of those controls to this property. This is requirement B.
Here's my first idea. I bind the current StudentData to a DP of StudentControl, then, inside the StudentControl, I change the data context to the control itself:
<UserControl DataContext="{Binding RelativeSource={RelativeSource Self}}">
<TextBox
Content="{Binding Path=ExposedStudentData.Field1}" *reqA*
IsEnabled="{Binding Path=OtherProperty1}" /> *reqB*
</UserControl>
This way, I figured, the StudentControl gets the StudentData from outside, exposes this same StudentData and the other new properties (so the data and other properties are in one place now, not two), and then I can bind to these exposed properties in XAML (reqA+reqB are fulfilled at the same time). Except this doesn't work because of this bug. Basically, if I set the DataContext of the control to itself, then it gets set before the outer binding is applied. So if my binding path inside the cell is X, and then the data context changes, the binding engine will look for X in the new, self data context, and not the outer, grid data context.
Here's my second idea. I bind the current StudentData to the DataContext or a DP of the StudentControl. Then, to access other exposed properties of the StudentControl, I give a name to the UserControl and use ElementName binding:
<UserControl x:Name="self">
<TextBox
Content="{Binding Path=Field1}" *reqA*
IsEnabled="{Binding ElementName=self, Path=OtherProperty1" /> *reqB*
</UserControl>
This way, I figured, the current data context is the StudentData, and it's not changed, and I can bind to that with a simple path (reqA), and I can bind to the other exposed properties with the ElementName stuff (reqB). It works in basic scenarios, but not in a DataGrid, because of this bug. I'm guessing the problem arises when there are multiple controls with the same name in the visual tree.
I'm really starting to hate Silverlight, I started using it a month ago, and I already reported 9 bugs. Whenever I try to achive something other than a simple hello world application or something that Microsoft and everyone else seems to be using Silverlight for, I encounter a new bug. So what now, how would you bind to a data class given from outside the control and some other properties exposed by the control at the same time? Without, of course, setting up the bindings from code (which I'm doing now, but it's a nightmare with ListBoxes and DataTemplates) or not using binding at all.
I think your problem is with the DataContext and how it is inherited, as well as namescopes.
For the first, you should know that if a control doesn't specify its own DataContext, it will inherit that of its parent, and for ItemsControl derived controls, each Item will have its DataContext set to one of the data items in the ItemsSource collection.
For your second problem, if you're inside a DataTemplate, you're in a different namescope than outside of it. You can't access controls "by name" outside of a DataTemplate. What you can do here (for Silverlight 4 and below) is to traverse the Visual Tree yourself and look for the control you want. This, however, is going to become much easier and less painful with some new features in SL5, specifically the "FindAncestor" feature (which already exist in WPF).
Here's an article on MSDN about Namescopes in Silverlight. And here's another one about DataBinding which mentions how DataContext is inherited.
To achieve what you're looking for, I think this blog post should help you. It shows you how to implement "RelativeSource Binding with FindAncestor"-like behavior in Silverlight.
Hope this helps :)
On another forum, they told me to use MVVM. As it turns out, it can make my first idea a little better. Instead of binding my StudentControl to a StudentData, and then exposing this data and other properties, I should create a viewmodel, let's say StudentControlData, which contains a StudentData and additional properties required by the control. If I bind my control to this, then in the inherited data context of the control, I have access to all properties that I need. Now the only problem left is that inside a ListBox in my StudentControl, I lose this data context.

How to bind the ItemSource inside the DataGrid to an element outside the DataContext, eg. ViewModel in Silverlight 4

I have a DataGrid with some text columns and a button. I want to bind button to a command on the ViewModel. Since, Columns are inside the context of the ItemSource, i want to change the DataContext for the button to something outside the DataGrid(to a view model, to access the Command) or else Silverlight is not able to find the binding expression for that command on the ItemSource context.
Here is what i am doing but i am unsuccessful in doing so. I am not sure where i am making a mistake
<DataGrid >
...
<Button>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:InvokeCommandAction Command="{Binding Path=DataContext.CommandToCall, ElementName=DataGridName}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
...
</DataGrid>
I do not get any Binding error on doing this but i cannot invoke the command inside my ViewModel. Please note, it is for silverlight and not WPF.
Thanks
I had this same problem recently. I was using a Telerik RadGridView, and I found a workaround on their support forum. Maybe you can do something similar.
Here's the question, and here's the workaround.

WPF - Binding a variable in an already bound ListBox?

I really don't know how to title this question, but I need some help with binding to a ListBox.
I have an object, that contains (among other information) 2 properties that need to be bound in one ListBox. One of these is an ObservableCollection of objects, called Layers, and the other property holds an enum value of either Point, Line or Polygon, called SpatialType. These are to act as a legend to a map application. I have bound Layers to a ListBox, no problem, but inside the ListBox.ItemTemplate, I need to bind the single variable SpatialType to every Item in the ListBox. The problem I'm running into is that when I try to bind while inside the ListBox, the only variables I have access to are the properties of each Layer and I can't access any properties of the original bound class that holds the Layers (and the needed SpatialType property).
What can I do to get that piece of information bound inside the ItemTemplate without messing up a good MVVM architecture?
You can in your view have a ObjectDataProvider that is the basis for your datacontext and have the ObjectInstance point to your viewmodel. Then you can bind from the ItemTemplate like so:
<UserControl.Resources>
<ObjectDataProvider x:Key="Data"/>
<DataTemplate x:Key="Template">
<TextBlock Text="{Binding SpatialType,Source={StaticResource Data}}/>
</DataTemplate>
</UserControl.Resources>
<Grid DataContext={Binding Source={StaticResource Data}}>
<ListBox ItemsSource="{Binding Layers}" ItemTemplate="{StaticResource Template}"/>
</Grid>
Hope this helps.
What I ended up doing was using FindAncestor to get the DataContext of a higher "tier" in binding:
Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBox}}, Path=DataContext.LayerSymbolization.SpatialType, Mode=TwoWay}"

Resources