从 ViewModel 设置条目的焦点

Posted

技术标签:

【中文标题】从 ViewModel 设置条目的焦点【英文标题】:Set focus of an entry from ViewModel 【发布时间】:2018-03-01 16:53:12 【问题描述】:

我已经阅读了有关消息传递、触发器、行为等的信息……对于我想要完成的工作来说,这一切似乎都有些矫枉过正。

我在 xaml 中有一个重复的数据输入屏幕,它有 1 个选择器、2 个条目和 1 个按钮。选择器一旦选择了一个值,就会保留该选择。第一个条目与选择器相同。第二个条目是始终获得新值的条目。

我想在单击按钮时收集填充的值,然后清除其数据的最后一个输入字段并将焦点重新放在该条目上,以便用户可以输入新值并点击保存。重复重复重复等。

我了解 MVVM 模型和理论 - 但我只想将重点放在 xaml 视图中的输入字段上,我完全被难住了。

编辑以添加代码示例

view.xaml:

<StackLayout Spacing="5" 
             Padding="10,10,10,0">
    <Picker x:Name="Direction" 
             Title="Select Direction" 
             ItemsSource="Binding Directions"
             ItemDisplayBinding="Binding Name"
             SelectedItem="Binding SelectedDirection"/>
    <Label Text="Order"/>
    <Entry Text="Binding Order" 
           x:Name="Order" />
    <Label Text="Rack"/>
    <Entry Text="Binding Rack" 
           x:Name="Rack" />
    <Button Text="Save" 
            Style="StaticResource Button_Primary" 
            Command="Binding SaveCommand"
            CommandParameter="x:Reference Rack" />
    <Label Text="Binding Summary"/>
</StackLayout>

viewmodel.cs

    public ICommand SaveCommand => new DelegateCommand<View>(PerformSave);

    private async void PerformSave(View view)
    
        var scan = new Scan()
        
            ScanType = "Rack",
            Direction = SelectedDirection.Name,
            AreaId = 0,
            InsertDateTime = DateTime.Now,
            ReasonId = 0,
            ScanItem = Rack,
            OrderNumber = Order,
            ScanQty = SelectedDirection.Value,
            IsUploaded = false
        ;

        var retVal = _scanService.Insert(scan);

        if (!retVal)
        
            await _pageDialogService.DisplayAlertAsync("Error", "Something went wrong.", "OK");
        
        else
        
            view?.Focus();
            Rack = string.Empty;
            Summary = "last scan was great";
        
    

此部分出现错误:

private void InitializeComponent() 
        global::Xamarin.Forms.Xaml.Extensions.LoadFromXaml(this, typeof(RackPage));
        Direction = global::Xamarin.Forms.NameScopeExtensions.FindByName<global::Xamarin.Forms.Picker>(this, "Direction");
        Order = global::Xamarin.Forms.NameScopeExtensions.FindByName<global::Xamarin.Forms.Entry>(this, "Order");
        Rack = global::Xamarin.Forms.NameScopeExtensions.FindByName<global::Xamarin.Forms.Entry>(this, "Rack");
    

【问题讨论】:

页面初始化部分出错 【参考方案1】:

您可以将条目作为View 参数发送到视图模型的命令。像这样:

public YourViewModel() 

    ButtonCommand = new Command<View>((view) => 
    
        // ... Your button clicked stuff ...
        view?.Focus();
    );

从 XAML 你这样称呼:

<Entry x:Name="SecondEntry" 
       ... Entry properties ...
       />
<Button Text="Click Me"
        Command="Binding ButtonCommand"
        CommandParameter="Reference SecondEntry"/>

希望对你有帮助。

【讨论】:

似乎无法正常工作...我在尝试获取 Entry 对象时遇到无效的转换错误 @BTI-Doug 你的意思是像var obj = (view as Entry);吗?您不需要专门将其作为条目。所有View 都有Focus 方法。你为什么要投射? @BTI-Doug 你忘记了CommandParameter="x:Reference Rack" 上的括号,它应该是CommandParameter="x:Reference Rack"...例如,我建议你将Entry 的名称更改为txtRack。它与 VM 的属性名称混淆 @cd491415 它可以为您带来即时便利,但这意味着您的视图模型应该了解您的整个视图,这不是一个好的选择。 @DiegoRafaelSouza 好点!但是对于从视图中了解 Entry 的 VM 是否同样适用?再次感谢【参考方案2】:

您可以在 XAML 中设置 CommandParameter 并在视图模型中使用它。

在 Xaml 中:

<ContentView Grid.Row="0" Grid.Column="0" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<Image Source="downarrow" HeightRequest="15" WidthRequest="15" VerticalOptions="Center" HorizontalOptions="End" Margin="0,0,5,0" />
<ContentView.GestureRecognizers>
      <TapGestureRecognizer Command="Binding SecurityPopupCommand" CommandParameter="x:Reference AnswerEntry"/>
</ContentView.GestureRecognizers>
</ContentView>

在视图模型中:

public ICommand SecurityPopupCommand  get  return new Command(OpenSecurityQuestionPopup);  
private void OpenSecurityQuestionPopup(object obj)

     var view = obj as Xamarin.Forms.Entry;
     view?.Focus();

【讨论】:

【参考方案3】:

不确定是否可以从 XAML 设置条目的焦点,但从页面中,您可以在 Clicked Event 上使用 Entry 的函数 Focus

saveButton.Clicked += async (s, args) =>

    //save the data you need here
    //clear the entries/picker
    yourEntry.Focus();
;

【讨论】:

我不希望条目始终获得焦点 - 只有在单击保存按钮后。 更新后的答案可以解决吗? @BTI-道格

以上是关于从 ViewModel 设置条目的焦点的主要内容,如果未能解决你的问题,请参考以下文章

Dagger/MissingBinding java.util.Map<java.lang.Class<? extends ViewModel>,Provider<ViewMo

使用 RelayCommand 从 ViewModel 中清除条目文本

从 ViewModel Xamarin 中的动态表单中获取条目值

OOP tkinter:如何将焦点(并添加文本)设置为条目?

MVVM

在ViewModel中使用getter而不是订阅Model