-2

I have a problem with binding with a XAML file. There is a DataContext of Template class that has a GetDisplayParams() method. Method GetDisplayParams() returns an object of type TemplateDisplayParams, that has a Width property. I just need to bind TextBox to this property, but nothing works for me.

.xaml:

<TextBox Text="{Binding GetDisplayParams.Width}"/> 

.axaml.cs:

public TemplateCompositeAttributesSettingsView(Scripting.Template dataContext) : this()
{
    DataContext = dataContext;
    Console.WriteLine( ((Scripting.Template)DataContext).GetDisplayParams().Width ); // return int.
}

Error: enter image description here

Tulesha
  • 9
  • 4
  • You can't bind to methods in WPF. Therefore you must assign the method result to a public property to which you can bind to. – BionicCode Sep 30 '21 at 16:42
  • @BionicCode, I would create a public property, but unfortunately, I do not have access to the source code of the Template class. I tried to create a property in TemplateCompositeAttributesSettingsView.cs and reassign the DataContext for the TextBox, but I get a System.Reflection.AmbiguousMatchException: "Ambiguous match found." – Tulesha Oct 01 '21 at 11:11
  • For example: if the template class is the DataContext of MainWindow, then you can call Template.GetDisplayParams method from the code-behind of the MainWindow. Create a dependency proeprty e.g., DisplayWidth on MainWindow that holds the result of the method call. Bind your TextBox to thid dependency property. You don't have to change the code of Template. If you need more help please provide the relevant code. You need to show the DataContext of the TextBox (how you set it). – BionicCode Oct 01 '21 at 11:19
  • @BionicCode, I eventually figured out this problem. Specified DataContext = TemplateCompositeAttributesSettingsViewModel for TextBox and created public property there. I'm new to WPF and Avalonia, so my question seemed silly to many. Thanks for the help. – Tulesha Oct 01 '21 at 11:30
  • No problem. You are welcome. – BionicCode Oct 01 '21 at 11:57

1 Answers1

0

As @BionicCode said, in WPF and I think Avalonia in XAML can't bind to methods. Therefore, I had to create a TemplateCompositeAttributesSettingsViewModel and specify a public property there and later bind the DataContext TextBox to this ViewModel.

.xaml

<StackPanel Name="MinWidthMinHeightStackPanel" Margin="3.5" Orientation="Horizontal">
            <!--TODO-->
            <TextBox Text="{Binding MinWidth}"/> 
            <TextBlock Margin="20,0,20,0" Text="x" VerticalAlignment="Center"/>
            <!--TODO-->
            <TextBox Text="{Binding MinHeight}"/>
</StackPanel>

TemplateCompositeAttributesSettingsView.cs:

public TemplateCompositeAttributesSettingsView(Scripting.Template dataContext) : this()
{
    DataContext = dataContext;
    var templateCompositeAttributesSettingsViewModel = new TemplateCompositeAttributesSettingsViewModel( dataContext );
    this.FindControl<StackPanel>( "MinWidthMinHeightStackPanel" ).DataContext = templateCompositeAttributesSettingsViewModel;
}

TemplateCompositeAttributesSettingsViewModel.cs:

class TemplateCompositeAttributesSettingsViewModel : ViewModelBase
{
    public TemplateCompositeAttributesSettingsViewModel(Scripting.Template DataContext)
    {
        this.DataContext = DataContext;
    }

    public int MinWidth
    {
        get => DataContext.GetDisplayParams().Width;
    }

    public int MinHeight
    {
        get => DataContext.GetDisplayParams().Height;
    }

    public Scripting.Template DataContext { get; set; }
}

Output: enter image description here

Tulesha
  • 9
  • 4
  • This is good. But note that the GetDisplayParams method is only called once. in case the returned result can change, your view will not get those changes. Binding to MinHeight and MinWIdth is like setting the binding mode to OneTime. – BionicCode Oct 01 '21 at 12:00
  • Also it is better to make TemplateCompositeAttributesSettingsViewModel a public readonly property and bind the StackPanel to it instead of assigning the DataContext in code-behind using FindControl. In this case the binding would look like this: ` ... ` – BionicCode Oct 01 '21 at 12:03