【问题标题】:Can't bind IsBusy property无法绑定 IsBusy 属性
【发布时间】:2016-09-17 19:31:22
【问题描述】:

我有一个带有以下代码的活动指示器的页面:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MyApp.ClientSearch" Title="Search">
  <ContentPage.Content>
    <StackLayout Orientation="Vertical">
      <StackLayout.Children>
        <SearchBar x:Name="txtSearchClient" TextChanged="OnTextChanged"></SearchBar>
        <ActivityIndicator IsVisible="{Binding IsBusy}" IsRunning="{Binding IsBusy}" x:Name="indicadorCargando" />
        <ListView x:Name="lstClients"></ListView>
      </StackLayout.Children>
    </StackLayout>  
  </ContentPage.Content>
</ContentPage>

在与此 xaml 关联的部分类中,我有:

namespace MyApp
{
    public partial class ClientSearch: ContentPage
    {
        public BusquedaClientes()
        {
            InitializeComponent();
        }

        async void OnTextChanged(object sender, TextChangedEventArgs e)
        {

            if (this.txtSearchClient.Text.Length >= 3)
            {
                var list_clients = App.ClientsManager.GetTasksAsync(txtSearchClient.Text);
                this.IsBusy = true;

                var template = new DataTemplate(typeof(TextCell));

                template.SetBinding(TextCell.DetailProperty, "name_ct");
                template.SetBinding(TextCell.TextProperty, "cod_ct");

                lstClients.ItemTemplate = template;
                lstClients.ItemsSource = await list_clients;

                this.IsBusy = false;

            }
        }
    }
}

如您所见,this.IsBusy 正在设置 Page 属性,因此尝试在 XAML 中绑定到该属性。不幸的是它不起作用:

<ActivityIndicator IsVisible="{Binding IsBusy}" IsRunning="{Binding IsBusy}" x:Name="indicadorCargando" />

如何将 ActivityIndi​​cator 的值绑定到 IsBusy 页面属性? 我已经知道像这样设置值:

this.IsBusy = true;
indicadorCargando.IsVisible=true; 
indicadorCargando.IsRunning=true;

但我不想那样做,我想设置一个值而不是三个。

【问题讨论】:

  • 1 - 为了清楚起见,您应该考虑将 View 和 ViewModel 分开 2- 您应该在 xaml 中添加 TextCell 3 - 您应该使用 e.Text

标签: xaml xamarin xamarin.forms


【解决方案1】:

您当然可以选择单独的视图模型,这不是一个坏主意。但是对于特定问题,您似乎没有在任何地方设置 BindingContext,因此它不会获得您想要的 IsBusy 属性。

我没有尝试将控件的 BindingContext 设置为自身,但是这样的东西应该可以工作:

<ActivityIndicator
  IsVisible="{Binding IsBusy}"
  IsRunning="{Binding IsBusy}"
  x:Name="indicadorCargando"
  BindingContext="{x:Reference indicadorCargando}" />

【讨论】:

    【解决方案2】:

    您需要为您的页面命名 (x:Name="myPage"),然后使用对它的引用声明绑定,并使用 {Binding Source={x:Reference myPage}, Path=IsBusy} 作为 ActivityIndi​​cator 的 IsVisibleIsRunning 值。有关this answer 的更多信息。

    【讨论】:

      【解决方案3】:

      我会这样重写它:

      public class ClientSearch : ContentPage
          {
              public ClientSearch()
              {
                  BindingContext = new ClientSearchViewModel();
                  var stack = new StackLayout();
                  var searchBar = new SearchBar();
                  searchBar.SetBinding<ClientSearchViewModel>(SearchBar.TextProperty, x => x.Text);
                  var actInd = new ActivityIndicator();
                  actInd.SetBinding<ClientSearchViewModel>(ActivityIndicator.IsVisibleProperty, x => x.IsBusy);
                  actInd.SetBinding<ClientSearchViewModel>(ActivityIndicator.IsRunningProperty, x => x.IsBusy);
                  var lv = new ListView
                  {
                      ItemTemplate = new DataTemplate(() =>
                      {
                          var txtCell = new TextCell();
                          txtCell.SetBinding<MyItemModel>(TextCell.TextProperty, x => x.Name_Ct);
                          txtCell.SetBinding<MyItemModel>(TextCell.TextProperty, x => x.Cod_Ct);
                          return txtCell;
                      })
                  };
                  lv.SetBinding<ClientSearchViewModel>(ListView.ItemsSourceProperty, x => x.items);
                  stack.Children.Add(searchBar);
                  stack.Children.Add(actInd);
                  stack.Children.Add(lv);
                  Content = stack;
              }
          }
      
          public class ClientSearchViewModel : BaseViewModel
          {
              public string Text { get; set; }
              public bool IsBusy { get; set; }
              public IEnumerable<MyItemModel> items { get; set; }
      
              protected override async void OnPropertyChanged(string propertyName = null)
              {
                  if (propertyName != nameof(Text) || Text.Length < 3) return;
                  IsBusy = true;
                  items = await App.ClientsManager.GetTasksAsync(Text);
                  IsBusy = false;
              }
          }
      
          [ImplementPropertyChanged]
          public abstract class BaseViewModel : INotifyPropertyChanged
          {
              public event PropertyChangedEventHandler PropertyChanged;
      
              protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-08-27
        • 2011-06-21
        • 2020-02-25
        • 2017-01-24
        • 2018-01-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多