Data binding in my custom control

MichaelRumplerMichaelRumpler ATMember ✭✭✭✭✭

I want to create my custom cell to basically replace

<ViewCell Height="300">
    <Editor Text="{Binding Template}" HeightRequest="300" />
</ViewCell>

by

<cells:EditorCell Text="{Binding Template}" Height="300" />

So I wrote the simple EditorCell like this:

public class EditorCell : ViewCell
{
    public static readonly BindableProperty TextProperty = BindableProperty.Create<EditorCell, string>(p => p.Text, null, BindingMode.TwoWay);

    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }

    public EditorCell()
    {
        var editor = new Editor();
        editor.SetBinding(Editor.TextProperty, (EditorCell ec) => ec.Text, BindingMode.TwoWay);
        editor.SetBinding(Editor.HeightRequestProperty, (EditorCell ec) => ec.Height, BindingMode.OneWay);

        View = editor;
    }
}

The Height property of my EditorCell is bound to the HeightRequest of the Editor as it should be, but the Text always remains null.

I set breakpoints in the constructor of EditorCell and in the getter and setter of the Text property. The constructor is hit, but the getter and setter are not. Neither during initial databinding nor later when I enter text in the Editor.
I checked that my viewmodel really contains text in its Template property and this text is used when I use the old xaml with the ViewCell.
If I deliberately misspell the Text property in my xaml, then I get an exception. So it should really use the correct property.

What am I doing wrong?
Could it be a problem that I bind the Text property to my viewmodel and at the same time to the Editor.TextProperty?

Best Answers

Answers

  • adamkempadamkemp USInsider, Developer Group Leader mod

    This line doesn't make sense to begin with:

    editor.SetBinding(Editor.TextProperty, (EditorCell ec) => ec.Text, BindingMode.TwoWay);
    

    You're binding the property to itself?

    Regardless, that binding is replaced in the XAML with {Binding Template}. Does that property exist on your view model? Does it have the right type? You may have to share more code, preferably a .zip.

  • GeorgeCookGeorgeCook PEUniversity ✭✭✭

    and, this got me at first as well : next to the "new discussion" button in the forum, there's a "ask question" button. It's best to use that for questions.

  • MichaelRumplerMichaelRumpler ATMember ✭✭✭✭✭

    I am trying to bind the Editors Text property to the EditorCells Text property.
    The next line binds the Editors HeightRequest property to the EditorCells Height property and that line works.

    Yes, my viewmodel does have a string property called Template and it contains a string with multiple lines of text. This text is shown if I replace my cell:EditorCell with the original ViewCell and the contained Editor.

  • adamkempadamkemp USInsider, Developer Group Leader mod

    Oh, I see. I read that line wrong.

    Could you attach a .zip with the code? It's much easier if I can just run it and see what's happening instead of making assumptions about the rest of the app.

  • MichaelRumplerMichaelRumpler ATMember ✭✭✭✭✭

    Thanks @GeorgeCook that helped.

    I removed the SetBinding for the Text property and synchronize the Text properties manually in the propertyChanged handler.

    Here is the complete code:

    public class EditorCell : ViewCell
    {
        public static readonly BindableProperty TextProperty = 
                BindableProperty.Create<EditorCell, string>(p => p.Text, null,
                    BindingMode.TwoWay, propertyChanged: OnTextChanged);
    
        public string Text
        {
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }
    
        private Editor editor;
    
        public EditorCell()
        {
            editor = new Editor();
            editor.TextChanged += (s, e) => Text = e.NewTextValue;
            editor.SetBinding(Editor.HeightRequestProperty, (EditorCell ec) => ec.Height, BindingMode.OneWay);
    
            View = editor;
        }
    
        private static void OnTextChanged(BindableObject bindable, object oldValue, object newValue)
        {
            var cell = (EditorCell)bindable;
            cell.editor.Text = (string)newValue;
        }
    }
    

    I will create a test project and attach it here. Would still be interesting to know why the original SetBinding call did not work.

  • GeorgeCookGeorgeCook PEUniversity ✭✭✭

    the original didn't get called because it won't - bindings do some voodoo in your class. If you use bindable properties, then you have to use the changing/changed handlers from the CreateBinding method. That took me a while to get my head around; but you just have to accept that once you create a binding, that's how it is.

  • MichaelRumplerMichaelRumpler ATMember ✭✭✭✭✭

    Well, I actually don't care if the property setter is called as long as the binding works. But it didn't.

    Here is a sample project.
    The Views/SimplePage.xaml shows three versions of that cell.

    1) a ViewCell with an Editor as View
    2) a Views/Cells/WorkingEditorCell which uses my workaround with manual binding
    3) a Views/Cells/NotWorkingEditorCell with the original code which used SetBinding

    It would be great if you could explain why the SetBinding does not work. I'll read the other thread George linked in the meantime.

  • MichaelRumplerMichaelRumpler ATMember ✭✭✭✭✭

    That makes sense. So I'll set the BindingContext of the Editor. Thank you!

    This would be so much easier if Xamarin would log binding errors also to the debug window like WPF does.

  • DerekBeattie.6675DerekBeattie.6675 US ✭✭
    edited April 2015

    @adamkemp When looking at the premade Cell's in reflector I don't see any layout. Maybe it's reflector but do those exist somewhere? So, for a TextCell I'd expect to see a vertical stacklayout somewhere with a Text and Detail label.

    edit: nevermind, I realized I was looking at the portable .dll and the layout stuff is probably in platform specific custom renderers.

  • adamkempadamkemp USInsider, Developer Group Leader mod

    The layout for those happens in the renderer.

  • rio_riyario_riya INMember ✭✭

    anybody tell how to customize the grouped shortname in the right side of the list view ?

Sign In or Register to comment.