.NET Maui将ContentView绑定到父ViewModel MVVM

huangapple go评论68阅读模式
英文:

.NET Maui Binding a contentview to parent ViewModel MVVM

问题

下面是您要翻译的内容:

I have a xaml page that contains two instances of the same content view. The content view have a datepicker which should update a value in the parent view model ( each content view should update a different variable in the view model). I tried to do the bindable property but it's not working. I set the BindingMode to TwoWay but that's not working.

The issue is that the binding is not working from the contentview to the parent viewmodel through the bindable property. Any input is much appreciated. 

Below is my code:
MainPage.xaml
TimeTrackerViewModel.cs
DateTimePickerContentView.xaml
and DateTimePickerContetntView.xaml.cs
英文:

I have a xaml page that contains two instances of the same content view. The content view have a datepicker which should update a value in the parent view model ( each content view should update a different variable in the view model). I tried to do the bindiable property but it's not working. I set the BindingMode to TwoWay but that's not working.

The issue is that the binding is not working from the contentview to the parent viewmodel through the bindiable property. Any input is much appreciated.

Below is my code:
MainPage.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
            BackgroundColor="{DynamicResource PageBackgroundColor}"
             xmlns:picker="clr-namespace:TestSync.View"
             xmlns:viewmodel="clr-namespace:TestSync.ViewModel"
             x:DataType="viewmodel:TimeTrackerViewModel"
             x:Class="TestSync.MainPage">

    <VerticalStackLayout>

        <Label Text="{Binding SelectedDate}"/>

        <Label Text="{Binding SelectedDate1}"/>

        <picker:DateTimePickerContentView CardTitle="First DatePicker" CardDate="{Binding SelectedDate,Mode=TwoWay}" />
        
        <picker:DateTimePickerContentView CardTitle="Second DatePicker" CardDate="{Binding SelectedDate1,Mode=TwoWay}" />
 
    </VerticalStackLayout>

</ContentPage>

TimeTrackerViewModel.cs

namespace TestSync.ViewModel
{
    public partial class TimeTrackerViewModel :ObservableObject
    {
        [ObservableProperty]
        public DateTime selectedDate;

        [ObservableProperty]
        public DateTime selectedDate1;
    }
}

DateTimePickerContentView.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:viewmodel="clr-namespace:TestSync.View"
             x:DataType="viewmodel:DateTimePickerContentView"
             x:Class="TestSync.View.DateTimePickerContentView"
             >
    <VerticalStackLayout>

        <Label Text="{Binding CardTitle}"/>
        <DatePicker x:Name="myDate" Date="{Binding CardDate}" />

    </VerticalStackLayout>
</ContentView>

and DateTimePickerContetntView.xaml.cs


namespace TestSync.View;

public partial class DateTimePickerContentView : ContentView
{
    public static readonly BindableProperty CardTitleProperty = BindableProperty.Create(nameof(CardTitle), typeof(string), typeof(DateTimePickerContentView), string.Empty);

    public string CardTitle
    {
        get => (string)GetValue(DateTimePickerContentView.CardTitleProperty);
        set => SetValue(DateTimePickerContentView.CardTitleProperty, value);
    }


    public static readonly BindableProperty CardDateProperty = BindableProperty.Create(nameof(CardDate), typeof(DateTime), typeof(DateTimePickerContentView), defaultValue:DateTime.Parse("12/15/1992"),defaultBindingMode:BindingMode.TwoWay,propertyChanged:test);

    private static void test(BindableObject bindable, object oldValue, object newValue)
    {
        var mytest= bindable as DateTimePickerContentView;
        mytest.myDate.Date = (DateTime)newValue;
    }

    public DateTime CardDate
    {
        get => (DateTime)GetValue(DateTimePickerContentView.CardDateProperty);
        set => SetValue(DateTimePickerContentView.CardDateProperty, value);
    }
    public DateTimePickerContentView()
	{
		InitializeComponent();
        BindingContext = this;
	}
}

答案1

得分: 1

我在这里为你提供一个解决方法。

对于 DateTimePickerContentView.xaml,定义 BindingContext

<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             ...
             x:Name="this">

    <VerticalStackLayout BindingContext="{x:Reference this}">
        <Label Text="{Binding CardTitle}"/>
        <DatePicker x:Name="myDate" Date="{Binding CardDate}" />
    </VerticalStackLayout>
</ContentView>

所以对于 DateTimePickerContentView.cs,只需删除这一行

...
public DateTimePickerContentView()
{
    InitializeComponent();
    //BindingContext = this;
}

对于 ContentView 中的数据绑定,你可以参考这个官方文档: Define the UI

如果你想设置一个默认值,你应该在 TimeTrackerViewModel 中设置,因为 TimeTrackerViewModel 的构造函数在自定义控件设置默认值之后执行。然后它会被替换,比如 1/1/1900。

public TimeTrackerViewModel()
{
    SelectedDate = DateTime.Parse("12/15/1992");
    SelectedDate1 = DateTime.Parse("12/15/1992");
}

希望对你有帮助。

英文:

I give you a workaround here.

For DateTimePickerContentView.xaml, define the BindingContext

&lt;ContentView xmlns=&quot;http://schemas.microsoft.com/dotnet/2021/maui&quot;
         xmlns:x=&quot;http://schemas.microsoft.com/winfx/2009/xaml&quot;
         ...
         x:Name=&quot;this&quot;&gt;

    &lt;VerticalStackLayout BindingContext=&quot;{x:Reference this}&quot;&gt;
        &lt;Label Text=&quot;{Binding CardTitle}&quot;/&gt;
        &lt;DatePicker x:Name=&quot;myDate&quot; Date=&quot;{Binding CardDate}&quot; /&gt;
    &lt;/VerticalStackLayout&gt;
&lt;/ContentView&gt;

So for DateTimePickerContentView.cs, just delete this line

...
public DateTimePickerContentView()
{
    InitializeComponent();
    //BindingContext = this;
}

For data binding in a ContentView, you could refer to this official doc: Define the UI.

And if you want to set a default value, you should set it in TimeTrackerViewModel, because TimeTrackerViewModel's constructor execute after custom control set the default value. Then it will be replaced such as 1/1/1900 .

public TimeTrackerViewModel()
{
    SelectedDate = DateTime.Parse(&quot;12/15/1992&quot;);
    SelectedDate1 = DateTime.Parse(&quot;12/15/1992&quot;);
}

Hope it works for you.

huangapple
  • 本文由 发表于 2023年2月16日 06:48:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/75466143.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定