How to bind to UITextView.EditingDidBegin in MvvmCross (Xamarin Studio) - c#

If there isn't already a binding for this - can somebody show me how to add a new binding for this (and register it)?
I've tried locating the UIButton.TouchUpInside binding handler code so I could copy that... without luck.
Thanks

Custom bindings are demonstrated and discussed in full in http://slodge.blogspot.co.uk/2013/06/n28-custom-bindings-n1-days-of-mvvmcross.html
Further, the 'built-in' custom bindings are all in https://github.com/slodge/MvvmCross/tree/v3/Cirrious/Cirrious.MvvmCross.Binding.Touch/Target
However, since EditingDidBegin is a standard EventHandler delegate (not a custom EventHandler<TEventArgs>) then there's no need for a custom binding - instead the standard binding should work:
var set = this.CreateBindingSet<FirstView, Core.ViewModels.FirstViewModel>();
set.Bind(textField).For("EditingDidBegin").To(vm => vm.MyEditingBeginCommand);
set.Apply();

Related

WPF password binding with passwordboxassistant through code

I'm trying to create a login screen but I want to do everything through code.
So generating the full UI through C#.
But I'm working with MVVM model and I have data binding on my username but this doesn't work on the standard PasswordBox so I found a namespace online which makes a workarround, it's called PasswordBoxAssistant from FunctionalFun.UI.
In the xaml I can create a passwordbox with the assistant but I'm making my UI through code and I'm not able to find how to use the PasswordBoxAssistant like that.
So I have this:
And want the same thing but in my C#
But like you see in my code, I don't have access to it.
No idea if the xaml will only be to access it with everything is compile or why I can't use it in my C#.
Anybody that can help me implement this or point me to a direction?
It seems PasswordBoxAssistant is an attached property similar to PassWordHelper here:
https://gist.github.com/alamsal/fcefce4fb2d2d70fb2d91ee12741a35f
You attach such properties as described here:
https://learn.microsoft.com/en-us/previous-versions/dotnet/netframework-4.0/ms749011(v=vs.100)#attached-properties-in-code
Hence something like
PasswordBoxAssistant.SetBindPassword(yourPasswordBox, true);
Would add that to a variable yourPasswordBox.
You then need to create a binding on the BoundPassword dependency property of course.
https://learn.microsoft.com/en-us/dotnet/desktop/wpf/data/how-to-create-a-binding-in-code?view=netframeworkdesktop-4.8
The property you are binding as target is the PasswordBoxAssistant dependency property.
Bindings are a bit fiddly in code. I have used the approach rarely.
A rough example:
Binding myBinding = new Binding();
// myBinding.Source = ViewModel; Datacontext is default, you probably don't need source.
myBinding.Path = new PropertyPath("SomeStringPropertyInDatacontext");
myBinding.Mode = BindingMode.TwoWay;
myBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
yourPasswordBox.SetBinding(PasswordBoxAssistant.BoundPasswordProperty, myBinding);

Winforms Databinding with a custom setter

I'm using some good old fashing DataBinding in a Winforms project.
I have my form with a control (A devExpress RichTextEdit for those that want to know)
I want to bind the HtmlText property of the richTextEdit control to a property on my ViewModel
I have done that binding and that is not a problem. However I have realised that the HtmlText that comes out of the richTextEdit is HtmlEncoded. Meaning that characters get encoded into their html entity representation.
eg < becomes < etc
I don't want this to happen as those tags have special meaning further down the line and I need to keep them.
So in my ViewModel that has all the notify property changed stuff and essentially wraps my domain object I could do this
public class ViewModel: INotifyPropertyChanged
{
public string WrappedProperty
{
get => domainObject.Property;
set
{
domainObject.Property = HttpUtility.DecodeHtml(value);
//Raise Property changed event etc
}
}
}
and in my form I create a Data binding
Binding binding = new Binding("HtmlText", _viewModel, "WrappedProperty", true, DataSourceUpdateMode.OnPropertyChanged,null,null);
_richEditControl.DataBindings.Add(binding);
now this works as intended, however I don't like it. My view model is doing things because of the control I am currently using. Its 'leaky' and it smells.
I want my View to be handle view specific issues.
What I'd like to do is to create a binding between the controls Html Text property and my View models WrappedProperty property, providing a custom function to be used when setting the property
from the control into the view model. Is is something that can be implemented or is there some kind of common work around pattern that I am missing?
Thanks
You can handle this in the binding using the Parse event.
Binding binding = new Binding("HtmlText", _viewModel, "WrappedProperty", true, DataSourceUpdateMode.OnPropertyChanged,null,null);
binding.Parse += (sender, e) => e.Value = HttpUtility.DecodeHtml(e.Value);
_richEditControl.DataBindings.Add(binding);
I managed to discover this myself, but as I struggled to find anything for a while on google about this I thought'd I'd myself and hopefully help future developers
There is an event on a Binding called Parse. Subscribing to this event allows to you to work with the value before it gets sent back to the data source.
Its partner is the Format event this allows you to work the value before it is displayed in the control
https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.binding.parse?view=netframework-4.8

Custom TypeDescriptor and AddValueChange/OnValueChanged

I’m exploring the use of custom TypeDescriptors to intercept when a data-bound property on a WPF control sets a CLR property. Due to reasons I need to figure out which exact control is setting a value.
If I use INotifyPropertyChanged I’ll get all of the different controls that subscribe to any property in my view model, not all that helpful. So I figured I’d go down the custom TypeDescriptor path and try the ProperyDescriptor.AddValueChanged and PropertyDescriptor.OnValueChanged way.
I can see that WPF calls ProperyDescriptor.AddValueChanged as expected, but my call to ProperyDescriptor.OnValueChanged never seems to trigger a call to PropertyDescriptor.GetValue and an update in the UI.
Are there some gotchas to using this stuff that I’m missing? Or are there other ways to figure out who’s subscribing to a CLR property. My alternative as I see it now would be to emit a custom proxy for the whole shebang, but I’d very much like to not have do that.
Edit: On looking at bit closer, I noticed that the delegates I get through PropertyDescriptor.AddValueChanged go to some internal MS helper class, so without some unreliable reflection-fu there's no way to use that to get the source control. I think I'll have to go with a custom proxy with dependency properties.
There's an alternative that may be useful. In a binding, you can set the NotifyOnSourceUpdated to True, which will raise the control's SourceUpdated event when WPF updates the CLR property it's data-bound to. For example, in a TextBox you can write:
<TextBox
Text="{Binding MyText, NotifyOnSourceUpdated=True}"
SourceUpdated="TextBox_OnSourceUpdated"
/>
In the code-behind, you can get the exact control (the sender) and the name of the dependency property that updated the CLR property:
private void TextBox_OnSourceUpdated(object sender, DataTransferEventArgs e)
{
var control = (TextBox)sender;
var propertyName = e.Property.Name;
}
With this method, you need to know that the control was a TextBox, but you can probably update it to test different kinds of controls. It depends on what you need this for, really.

Caliburn Micro Winforms MEF Implementation

My name is Max. I'm currently working on a projekt with caliburn micro.
I'm trying to create a plugin based application in C# with the help of MEF.
I'm using WPF. So I stripped my application to the bare minimum. The bindings with caliburn works fine in the test WPF application. The problem what I have now is that the ShellView (WPF UserControl) needs to live in an ElementHost of a WinForm 3rd party application.
I can't figure it out how to create the correct binding. So that the "magic" of caliburn also works in the winform application. Maybe one of you cracks can help me. I googled and tried this an entire day.
Your help would be very much appreciated.
Greets Max
Link to project:
https://www.dropbox.com/s/y88kgnh0wscy2jr/CaliburnMEF_Example.zip?dl=0
Sample that was provided on the CM GitHub its been there a while..., https://github.com/Caliburn-Micro/Caliburn.Micro/tree/master/samples/Caliburn.Micro.WinFormsInterop/Caliburn.Micro.WinFormsInterop
--edit--
You were close compare this code snippet to your current test project. You were missing a few key items... reference comments
protected override void StartRuntime()
{
base.StartRuntime();
var vm = IoC.Get<ShellViewModel>(); // ok
var view = ViewLocator.LocateForModel(vm, null, null); // needed
//binds the viewmodel to the view & wire up controls...
ViewModelBinder.Bind(vm, view, null); // required!
var activator = vm as IActivate; // required
if (activator != null)
activator.Activate(); // required
_host.Child = view; // since Forms is ViewFirst, by default.
}
Just a few extra steps to get it work with the ElementHost control. As for binding it should work as expected. If you are having issues with binding other controls (3rd party), you might have to create Conventions to support them. That is a very dependent on the controls themselves.

Bindings not applied to dynamically-loaded xaml

I'm using XamlReader successfully to load a xaml file and create a FrameworkElement to work with.
The xaml I'm loading has binding expressions in it such as:
<TextBlock Text="{Binding DataContextTextProperty}" />
If I place the FrameworkElement I get back from XamlReader.Load() into a WPF window, the binding all works fine.
However, in this case I'm using Laurent Bugnion's excellent article on creating PNGs from WPF/XAML. Since the result of XamlReader.Load() is written directly to a PNG via a VisualBrush, it seems the necessary mechanics of WPF to invoke binding expressions are bypassed.
This leads me to believe that the actual bindings aren't really being invoked just by calling XamlReader.Load(), or that they're not working because of something I don't know about to do with there not being a visual tree until you add the FrameworkElement to an existing visual tree or something.
Is there something I can do to ensure these bindings are invoked?
Many thanks in advance.
I FIXED IT!!
Ahem, allow me to explain...
I have no idea how I got to it now, but I found a helpful-sounding article on MSDN regarding Initialization for Objects Not in an Object Tree.
In it I found the following code example:
Button b = new Button();
b.BeginInit();
b.Background = Brushes.Blue;
b.Width = b.Height = 200;
b.EndInit();
b.Measure(paperSize);
b.Arrange(new Rect(paperSize));
b.UpdateLayout();
I looked at the (again, excellent) example from Laurent that I mentioned in the question above, and customised the use of XamlReader as follows:
var element = (FrameworkElement)XamlReader.Load(xamlInput);
element.BeginInit();
element.DataContext = dataContext;
...
element.Measure(renderingSize);
element.Arrange(renderingRectangle);
element.EndInit();
element.UpdateLayout();
I added the BeginInit(), EndInit() and UpdateLayout() (though by process of elimination I believe UpdateLayout() is the key) and now the binding expressions in my dynamically-loaded xaml are working correctly. Hurrah!

Categories

Resources