如何简单地展示一个MvxDialogFragment?

3

我正在尝试使用MvxDialogFragment在活动中展示一个数据绑定的对话框。我的对话框视图模型如下:

public class ContainerDialogViewModel : MvxViewModel
{

    public string ShipperName;

    public void Init(string Name)
    {
        ShipperName = Name;
        LoadData();
    }

    public void LoadData()
    {
        Survey = SurveyDataSource.CurrSurvey;
    }

    private ShipmentSurvey _Survey;
    public ShipmentSurvey Survey
    {
        get
        {
            return _Survey;
        }
        set
        {
            _Survey = value;
            RaisePropertyChanged(() => Survey);
            RaisePropertyChanged(() => Containers);
        }
    }


    public List<ShipmentSurveyContainer> Containers
    {
        get
        {
            if (Survey == null)
                return new List<ShipmentSurveyContainer>();
            else
                return Survey.SurveyContainers.ToList();
        }
    }

}

MvxDialogFragment的代码如下:
public class ContainerDialog : MvxDialogFragment<ContainerDialogViewModel>
{
    public override Dialog OnCreateDialog(Bundle savedState)
    {
        base.EnsureBindingContextSet(savedState);

        this.BindingInflate(Resource.Layout.ContainerDialog, null);

        return base.OnCreateDialog(savedState);
    }

}

在我的活动中,我正在尝试找到启动对话框的最简单方法。以下是我尝试过的方法:

public class SurveyView : MvxActivity
{
    public void ShowContainerDialog()
    {
        ContainerDialogViewModel vm = new ViewModels.ContainerDialogViewModel();
        vm.Init("Test Name");
        var dialogFragment = new ContainerDialog()
        {
            DataContext = vm
        };
        dialogFragment.Show(FragmentManager, "Containers");
    }
}

我很确定我的创建视图模型的方法是不正规的,但我不知道其他的方法。最大的问题是FragmentManager被转换成了错误的版本。Show正在寻找一个Android.Support.V4.App.FragmentManager,而暴露出来的FragmentManager是一个Android.App.FragmentManager。我尝试将MvxActivity更改为MvxFragmentActivity,但这似乎没有帮助。有人可以指引我正确的方向吗?


计划在5.1.0版本中推出一个新的支持对话框的演示者。 - undefined
@Martijn00 现在有没有办法让它工作?比如使用自定义的 presenter 或者其他类似的方法?我已经费尽心思寻找一个可用的 MvxDialogFragment 的示例,但是一直没有找到。 - undefined
我正在处理这个问题:https://github.com/MvvmCross/MvvmCross/issues/1934 - undefined
@Martijn00 谢谢兄弟。我看了一下链接,大部分内容可能超出了我的能力范围,但如果有需要的话,我或许可以测试其中的一些内容。如果有我能贡献的地方,请告诉我。 - undefined
@Martijn00 我已经安装了5.4版本。现在有办法做到这一点吗?你能给我一个例子吗? - undefined
现在一切都在这里了:https://github.com/MvvmCross/MvvmCross/tree/develop/TestProjects/Playground - undefined
2个回答

6

在我尝试实现它时,MvvmCross并不真正支持这个功能,但我遇到了另一个需要它的情况,结果发现该功能已经存在。感谢@Martijn00指向解决方案。这可能非常基础,但我认为它可能会对某些人有所帮助。

我的布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:local="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
  <TextView
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      style="@style/TableHeaderTextView"
      android:text="Work Date"/>
  <MvxDatePicker
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textSize="20dp"
    local:MvxBind="Value WorkDate" />
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Close"
        local:MvxBind="Click CloseCommand" />
</LinearLayout>

我的视图模型:

public class HoursDateDialogViewModel : MvxViewModel<EstimateHours>
{
    private readonly IMvxNavigationService _navigationService;

    public HoursDateDialogViewModel(IMvxNavigationService navigationService)
    {
        _navigationService = navigationService;

        CloseCommand = new MvxAsyncCommand(async () => await _navigationService.Close(this));
    }

    public override System.Threading.Tasks.Task Initialize()
    {
        return base.Initialize();
    }

    public override void Prepare(EstimateHours parm)
    {
        base.Prepare();
        Hours = parm;
    }

    public IMvxAsyncCommand CloseCommand { get; private set; }

    private EstimateHours _Hours;
    public EstimateHours Hours
    {
        get
        {
            return _Hours;
                }
        set
        {
            _Hours = value;
            RaisePropertyChanged(() => Hours);
            RaisePropertyChanged(() => WorkDate);
        }
    }

    public DateTime WorkDate
    {
        get
        {
            return Hours.StartTime ?? DateTime.Today;
        }
        set
        {
            DateTime s = Hours.StartTime ?? DateTime.Today;
            DateTime d = new DateTime(value.Year, value.Month, value.Day, s.Hour, s.Minute, s.Second);
            Hours.StartTime = d;
            DateTime e = Hours.EndTime ?? DateTime.Today;
            d = new DateTime(value.Year, value.Month, value.Day, e.Hour, e.Minute, e.Second);
            Hours.EndTime = d;
            RaisePropertyChanged(() => WorkDate);
        }
    }

}

我的观点:

[MvxDialogFragmentPresentation]
[Register(nameof(HoursDateDialogView))]
public class HoursDateDialogView : MvxDialogFragment<HoursDateDialogViewModel>
{
    public HoursDateDialogView()
    {
    }

    protected HoursDateDialogView(IntPtr javaReference, JniHandleOwnership transfer)
        : base(javaReference, transfer)
    {
    }

    public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        var ignore = base.OnCreateView(inflater, container, savedInstanceState);

        var view = this.BindingInflate(Resource.Layout.HoursDateDialogView, null);

        return view;
    }
}

就是这样。我可以传递参数对象并将对象的一部分绑定到MvxDatePicker。为了显示此对话框,在您的Setup.cs中,首先需要:

    protected override IMvxAndroidViewPresenter CreateViewPresenter()
    {
        return new MvxAppCompatViewPresenter(AndroidViewAssemblies);
    }

在您将要打开对话框的视图模型中,您需要包含一个构造函数:
    private readonly IMvxNavigationService _navigationService;

    public LocalHourlyViewModel(IMvxNavigationService navigationService)
    {
        _navigationService = navigationService;
    }

这将注入导航服务,以便您可以使用它。最后,打开对话框所需的所有操作只有:

async () => await _navigationService.Navigate<HoursDateDialogViewModel, EstimateHours>(Item);

我甚至不确定你是否需要等待呼叫,但我正在遵循示例。您可以在@Martijn00提供的链接中查看更多示例:

https://github.com/MvvmCross/MvvmCross/tree/develop/TestProjects/Playground

干杯!


+1 另外,托管 MvxDialogFragment 的活动必须是 MvxFragmentActivity。我知道在其他帖子中已经提到过,但为了完整起见,我再次强调一下。 - undefined
@EvaLan 只是为了记录,托管的 Activity 也可以是 MvxAppCompatActivity。这是我通常使用的。干杯 :) - undefined

0
我尝试将MvxActivity更改为MvxFragmentActivity。
这是正确的第一步。然后,不要传入FragmentManager,而是传入SupportFragmentManager。
如果对Support Libraries不熟悉,可以阅读有关它们是什么以及如何在Xamarin中使用它们的更多信息here

你的建议使得程序编译正确并运行,但是当对话框显示时,内容为空白。它正在填充视图,所以我不确定接下来该怎么做。 - undefined
1
@JimWilcox - 不要使用OnCreateDialog,而是覆盖OnCreateView方法并在其中填充你的布局。你可以摒弃OnCreateDialog。请查看此代码块中的注释以获取更多信息:https://dev59.com/g2Yr5IYBdhLWcg3w8-vA#19302991 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接