如何将 viewmodel 变量绑定到 xamarin 形式的 ObservableCollection 项?

how to bind a viewmodel variable to ObservableCollection items in xamarin form?

我有一个任务列表,我需要将布尔变量绑定到它的项目。 任务对象包含一个 completedDate 属性,如果它有值,则将任务定义为已完成。 在视图中,我需要检查按钮文本是否具有显示文本的值:“标记为不完整”

----任务对象-----

   public class ProjectTaskLineItemSummary
{
    
    public int TenantId { get; set; }
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }      
    public decimal? CostMultiplier { get; set; }
    public DateTimeOffset? CompletedDate { get; set; }
    public int? CompletedByUserId { get; set; }

    
}

--------视图模型--------

 viewmodel()
{
 public ObservableCollection<ProjectTaskLineItemSummary> Tasks { get; set; }
...

  bool isCompleted;
        public bool IsCompleted
        {
            get {
                return isCompleted;
                    }
            set
            {
                isCompleted = value;

                OnPropertyChanged();
            }
        }
}

-----查看----

 <CollectionView  Grid.Row="1" ItemsSource="{Binding Tasks}" x:Name="List3">
                                <CollectionView.ItemTemplate>
                                    <DataTemplate>
                                        <Grid>
                                            <Frame
                                        Margin="0,10"
                                        Padding="10"
                                        BackgroundColor="{StaticResource PrimaryWhite}"
                                        BorderColor="{StaticResource PrimaryLightGray}"
                                        CornerRadius="10"
                                        HasShadow="False">
                                                <Grid RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto" RowSpacing="15">
                                                  
                                                       
                                                        <StackLayout HorizontalOptions="EndAndExpand" Orientation="Horizontal">
                                                            <Image
                                                        HeightRequest="20"
                                                        Source="iconCalender.png"
                                                        WidthRequest="20" />
                                                            <Label
                                                        FontFamily="{StaticResource MeduimFont}"
                                                        Style="{StaticResource LabelMedium}"
                                                        Text="{Binding CompletedDate,StringFormat='{0:MMMM dd, yyyy}'}"
                                                        TextColor="{StaticResource PrimaryBlack}" 
                                                        />
                                                        </StackLayout>
                                                    </StackLayout>

                                                    <BoxView
                                                Grid.Row="1"
                                                HeightRequest="1"
                                                Color="{StaticResource PrimaryLightGray}" />

                                                    <Label
                                                Grid.Row="2"
                                                Style="{StaticResource LabelMedium}"
                                                Text="{Binding Name}"
                                                TextColor="{StaticResource PrimaryBlack}" />
                                                    


                                                    <Button
                                                x:Name="lstbtnMarkasComplite"
                                                Grid.Row="5"
                                                Padding="15,0"
                                                Clicked="MarkTaskAsCompletedClicked"
                                                CornerRadius="20"
                                                FontSize="{StaticResource Font12}"
                                                HeightRequest="40"
                                                         CommandParameter="{Binding Id}"
                                                HorizontalOptions="CenterAndExpand"
                                                Style="{StaticResource ButtonPurple}"
                                                Text="Mark as Completed" >
                                                        <Button.Triggers>
                                                            <DataTrigger TargetType="Button" Binding="{Binding IsCompleted}" Value="True">
                                                                <Setter Property="Text" Value="Mark Task as In Completed"/>
                                                            </DataTrigger>

                                                        </Button.Triggers>
                                                    </Button>

                                                </Grid>
                                            </Frame>
                                        </Grid>
                                    </DataTemplate>
                                </CollectionView.ItemTemplate>
                            </CollectionView>

我尝试在视图模型中分配它,如下所示,但它不起作用:

public override async Task InitializeAsync(object navigationData)
        {
            await SetBusyAsync(async () =>
            {
...

                Tasks = ObjectMapper.Map<ObservableCollection<ProjectTaskLineItemSummary>>(project.TaskLineItems);

                foreach (var task in Tasks)
                {
                    isCompleted = task.CompletedDate.HasValue ? true : false;
                }
                RaisePropertyChanged(() => Model);
                RaisePropertyChanged(() => Notes);
                RaisePropertyChanged(() => Files);
                RaisePropertyChanged(() => Tasks);

            });
        }

这可以简单地通过按钮的Binding Text 属性然后根据CompletedDate动态设置按钮的Text来实现实体的。 以下是供您参考的代码片段:

型号: ProjectTaskLineItemSummary.cs

public class ProjectTaskLineItemSummary
    {
        public int TenantId { get; set; }
        public int Id { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        public decimal? CostMultiplier { get; set; }
        public DateTimeOffset? CompletedDate { get; set; }
        public int? CompletedByUserId { get; set; }
        public string CompletedButton { get; set; } 
    }

查看:

 <CollectionView  ItemsSource="{Binding Tasks}" x:Name="List3" Background="aqua">
        <CollectionView.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Frame Margin="0,10" Padding="10"  HasShadow="False">
                        <Grid RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto" RowSpacing="15">
                            <StackLayout HorizontalOptions="EndAndExpand" Orientation="Horizontal">
                                <Image HeightRequest="30" Source="XamarinLogo.png" WidthRequest="80" />
                                <Label x:Name="mydate" Text="{Binding CompletedDate,StringFormat='{0:MMMM dd, yyyy}'}" TextColor="Black"/>
                            </StackLayout>

                            <BoxView Grid.Row="1" HeightRequest="1" Color="Black" />

                            <Label Grid.Row="2"  Text="{Binding Name}" TextColor="Black" />

                            <Button Grid.Row="5" x:Name="lstbtnMarkasComplite" Padding="15,0" 
                                                Clicked="MarkTaskAsCompletedClicked"
                                                CornerRadius="20"
                                                Text="{Binding CompletedButton}"
                                                FontSize="Medium"
                                                HeightRequest="40"
                                                CommandParameter="{Binding Id}"
                                                HorizontalOptions="CenterAndExpand">
                            </Button>

                        </Grid>
                    </Frame>
                </Grid>
            </DataTemplate>
        </CollectionView.ItemTemplate>
    </CollectionView>

ViewModel:

 public class PageViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public ObservableCollection<ProjectTaskLineItemSummary> Tasks { get; set; }
        bool isCompleted { get; set; }
        public bool IsCompleted
        {
            get => isCompleted;
            set
            {
                isCompleted = value;

                PropertyChanged?.Invoke(this,
                   new PropertyChangedEventArgs(nameof(IsCompleted)));
            }
        }
        string completed { get; set; }
        public String CompletedButton
        {
            get => completed;
            set
            {
                completed = value;
                PropertyChanged?.Invoke(this,
                 new PropertyChangedEventArgs(nameof(CompletedButton)));
            }
        }
        public PageViewModel()
        {
           
            Tasks = new ObservableCollection<ProjectTaskLineItemSummary>()
            {

                new ProjectTaskLineItemSummary(){TenantId = 1, Id =1, Name = "jobs ", Description= "jjjj",CostMultiplier=1 ,CompletedDate =DateTime.UtcNow, CompletedByUserId=1 ,CompletedButton = ""},
                new ProjectTaskLineItemSummary(){TenantId = 2, Id =2, Name = "james ",Description= "aaaa",CostMultiplier=2 , CompletedByUserId=2,CompletedButton = "" },
                new ProjectTaskLineItemSummary(){TenantId = 3, Id =3, Name = "rollex ",Description= "rrrr",CostMultiplier=3 ,CompletedDate =DateTime.UtcNow, CompletedByUserId=3 ,CompletedButton = ""}
            };
            setButtonIsCompleted();
        }

        private void setButtonIsCompleted()
        {
           foreach (var task in Tasks)
            {
                if (task.CompletedDate == null)
                {
                     task.CompletedButton = "Mark Task as Completed";
                }
                else
                {
                    task.CompletedButton = "Mark Task as inCompleted";
                }
            }
        }
    }