I wonder if it is possible in UWP to bind to a converter like this:
{Binding Path=Value, Converter={Binding ElementName=control, Path=Converter, Mode=OneWay}, Mode=TwoWay}"
I need this for a UserControl, on which the consumer can set the Converter property according to his needs. The binding expression above doesn't work for me, but I'm not sure if it is because I've done something wrong or if it is because the framework doesn't support it.
Binding.Converter is regular property not a DependencyProperty thus binding won't work here. Like MSDN says:
A binding target. This is a DependencyProperty of the FrameworkElement in your UI that displays the data.
More information about Data Binding you will find at MSDN.
Related
I am using PRISM with xamarin forms, and I like to declare my viewmodels in the XAML,
xmlns:local="clr-namespace:MyProyect.ViewModels"
……
<ContentPage.BindingContext>
<local:RegistroPageViewModel />
</ContentPage.BindingContext>
so I can have XAML intellicense, in this sample my RegistroPageViewModel constructor have one parameter beacause it need for the base class but I don't know how to pass it within the xaml
public class RegistroPageViewModel : ViewModelBase
{
public RegistroPageViewModel(INavigationService navigationService):base(navigationService)
{
registro = new RegistroInfo();
Title = "Perfil de usuario";
}
My specific question is: How can I still using XAML viemodels's declaration if the viewmodel have a parameter ? how can I pass a parameter in the XAML declaration?
thnaks in advance
For XAML to know about ViewModel, enable XamlC and Compiled Bindings. Documentation provides how to enable and use them properly.
XamlC checks for general compile time errors like property names and open-closing matching tags etc...
Compiled Bindings checks for existence of any property that is bound
You can use the view model locator (ViewModelLocator.AutowireViewModel="True") to have the view model created for you with all dependencies automatically injected.
Setting the view model as design data context (d:DataContext={d:DesignInstance local:RegistroPageViewModel}) should give you intellisense.
I have just fired up a WPF project and I want to use Caliburn.Micro.
I have a button
<Button Content="Button" Name="AppendData">
and in my ViewModel I have a method void AppendData(){..}
It doesn't work! There is no binding between the two! But when I do this
<Button Content="Button" cal:Message.Attach="AppendData()">
it suddenly works. What can be the cause of this?
Edit:
I have created a test application where the conventions doesn't work: http://ge.tt/8sNsu201?c
You can make it work, by replacing the controls in MyView with
<Button cal:Message.Attach="SetText()" Content="Button" HorizontalAlignment="Left" Margin="106,153,0,0" VerticalAlignment="Top" Width="75"/>
<Label Content="{Binding Text}" HorizontalAlignment="Left" Margin="124,104,0,0" VerticalAlignment="Top"/>
After taking a look at your source code, I noticed a major mistake which is causing all of this confusion:
public MyView()
{
InitializeComponent();
DataContext = new MyViewModel(); // SOURCE OF TROUBLE
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}
In Caliburn.Micro you don't set the DataContext for your view manually like that, instead you let Caliburn.Micro use its conventions to find the appropriate view for your view-model, then it will bind the two together (by setting the view-model as the DataContext of the view), after that it will apply a number of conventions to make everything work correctly.
Explaining why using cal:MessageAttach() would work and directly using AppendData won't work would take a lot of explanation because it seems you don't know the basics of CM.
So I advise you to take a look at the documentation wiki first and go through the first 5 articles at least, then here is a hint that will help you discover why the first method worked and the second didn't:
Message Bubbling
Because this would expand the comments maximum length, I write it as an answer.
As you mentioned in your answer, doing DataContext = new MyViewModel() is a kind of code smell in CM. If you want to hook up it manually in your view, this would be the right way (view first). Check out the CM documentation regarding this one though, because I think there might be missing something:
var viewModel = new MyViewModel();
var view = this;
ViewModelBinder.Bind(viewModel, view, null);
You can accomplish this in the XAML of your view, either. Add the following into the UserControl tag of your view (view first, as well):
xmlns:cal="http://www.caliburnproject.org"
cal:Bind.Model="MyViewModel"
View model first would be done quite the same, in case you are not willing to use the default behavior you described in your answer:
xmlns:cal="http://www.caliburnproject.org"
cal:View.Model="MyViewModel"
I am not sure, but I think you have to add an explicitly named export contract to your view model, if you want to use View.Model or Bind.Model, but it might be it works without as well. Try it out:
[Export("MyViewModel", typeof(MyViewModel))]
public class MyViewModel : Screen
{
// ...
}
Design time views have nothing to do with view first or view model first though!
Design-time view support is accomplished as follows:
xmlns:cal="http://www.caliburnproject.org"
d:DataContext="{d:DesignInstance viewModels:MyViewModel, IsDesignTimeCreatable=True}"
cal:Bind.AtDesignTime="True"
I am currently not able to test all those things, so I hope there are not any mistakes!
In mvvm-light, it comes with two property-creation snippets: mvvminpc to create a 'normal' property; and mvvmpropa to create an attached property (aka dependency property). I just want to know if there is any guidance on what to take into consideration when choosing which one to use?
I've been also searching for a while on these property topics for MVVM light. Below is my understanding of the property snippets provided in MVVM light. There aren't really any cases where you would use one over the other because they are for different purposes.
Bindable Property - Bindable properties are created in your ViewModels to expose data which your view will display.
Examples include: Displaying a collection of Employees, or the selected employee information.
Dependency Property - View specific when it comes to the code snippet. These properties can be set to a constant value or use data binding for changes depending on the viewmodel data.
Examples include: A textblock control's "Text" property is a dependency property. The "Height" and "Width" properties are also dependency properties.
Attach Property - Also used more specifically for user controls. This property is added to a parent control. Child controls use these properties to behave a certain way within the parent control.
Example includes: a Dockpanel has a "Dock" (Attached Property Name) that isn't used by the Dockpanel itself. It is used by the children contained inside of it, the children will now be able to set the property: DockPanel.Dock="Top".
<DockPanel>
<TextBlock Text="{Binding EmployeeName}" DockPanel.Dock="Top" />
<Button Content="Click Here" DockPanel.Dock="Bottom" />
</DockPanel>
In the example code above:
The Bindable Property is the EmployeeName, which would be a public property in the viewmodel code.
The Dependency Property is the Text="" property of the textblock and the Content="" property of the button.
The Attach Property is the DockPanel.Dock property used in the Textblock and button, but is actually exposed by the Dockpanel itself. Notice that the Dockpanel doesn't contain any of the .Dock code, only the children do.
Dependency properties are recommended when you create UI components (controls, etc.): they have better time performances for binding.
Normal properties are used if you have business object or if you dont have/create UI controls.
I've got a model class with custom change events, which is working fine if I make a reference to that class in my mxml using;
[Bindable] private var firstClass:FirstClass;
The objects gets filled by a server side script, so don't worry, firstClass isn't null.
Anyhow, accessing firstClasses properties in mxml works perfectly fine using curly brackets. The binding works just as expected.
However, is there any way to access firstClasses properties and set them to say a label with pure Actionscript.
lblTest.text = firstClass.property;
The code above doesn't work. I suppose because it sets a fixed value to the label.
I'm aware of using BindingUtils.bindProperty to explicitly set the source and destination for the binding. However, this turned out to cause huge performance issues in my (mobile) application.
So is there a simpler, more efficient way to do this?
No. The BindingUtils uses propertyChanged events to detects when an object's property changes. You won't be able to bind something without listening to events, and the most painless way to do it is using BindingUtils.
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.