0

虽然这个问题似乎被问了很多次,但我似乎找不到正确的解决方案,或者把各个部分放在一起来解决这个问题。

CollectionView在集合视图中有一个 with Bindable.Stacklayout

嵌套的 Stacklayout 包含一个Checkbox,并且该复选框的可见性由父列表(CollectionView)数据源的属性设置。

这最初在加载时可以正常工作,但是,一旦父属性更改(它还处理嵌套堆栈布局的可见性),那么嵌套堆栈布局的 UI 就不会更新。问题是,我怎样才能做到这一点?

XAML:

<CollectionView
    ItemsSource="{Binding RoomsData}"
    SelectionMode="None">

    <CollectionView.ItemTemplate>
        <DataTemplate>
            <xct:Expander
                x:Name="RoomExpander"
                IsExpanded="{Binding IsExpanded}">
                
                <xct:Expander.Header>
                    <! -- omitted code -->
                </xct:Expander.Header>
                
                <xct:Expander.Content>

                    <StackLayout                                
                        BindableLayout.ItemsSource="{Binding Elements}">
                        
                        <BindableLayout.ItemTemplate>
                            <DataTemplate>
                                <Grid>

                                    <!-- omitted / simplified code a bit for readability -->
                                    <CheckBox IsVisible="{Binding RoomsData.ElementsVisible}" />
                                    
                                </Grid>

                            </DataTemplate>
                        </BindableLayout.ItemTemplate>
                                                        
                    </StackLayout>
                                                
                </xct:Expander.Content>

            </xct:Expander>

        </DataTemplate>
    </CollectionView.ItemTemplate>
</CollectionView>

楷模):

// Main datasource
public IList<RoomModel> RoomsData
{
    get { return _roomsData; }
    set { SetProperty(ref _roomsData, value); }
}

public class RoomModel : ObservableObject
{
    // Other properties omitted.. 

    private bool _elementsVisible;

    public bool ElementsVisible
    {
        get { return _elementsVisible; }
        set { SetProperty(ref _elementsVisible, value); }
    }

    public IList<ElementModel> Elements { get; set; }
}

public class ElementModel : ObservableObject
{
    // Other properties omitted.. 
}

* SetProperty 包含 NotifyPropertyChanged 逻辑

在某个时刻,ElementsVisible属性从 false 变为 true 或反之亦然,然后我希望嵌套堆栈布局的复选框改变可见性,但没有任何反应。我应该通知Elements嵌套数据源来实现这一点吗?

4

1 回答 1

1

As Jason's opinion, you have some problems for Xamarin.Forms Relative Bindings, I do one sample that you can take a look. If I change ElementsVisible, the UI will update.

<StackLayout>
        <CollectionView
            x:Name="collectionview"
            ItemsSource="{Binding RoomsData}"
            SelectionMode="None">
            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <Expander x:Name="expander" IsExpanded="{Binding IsExpanded}">
                        <Expander.Header>
                            <Label
                                FontAttributes="Bold"
                                FontSize="Medium"
                                Text="test" />
                        </Expander.Header>
                        <StackLayout BindableLayout.ItemsSource="{Binding Elements}">
                            <BindableLayout.ItemTemplate>
                                <DataTemplate>
                                    <StackLayout>
                                        <!--  omitted / simplified code a bit for readability  -->
                                        <CheckBox IsVisible="{Binding Path=BindingContext.ElementsVisible, Source={x:Reference expander}}" />
                                        <Label Text="{Binding str}" />
                                    </StackLayout>
                                </DataTemplate>
                            </BindableLayout.ItemTemplate>
                        </StackLayout>
                    </Expander>

                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>

        <Button
            x:Name="btn1"
            Clicked="btn1_Clicked"
            Text="change data" />
    </StackLayout>
 public partial class Page11 : ContentPage
{
    public ObservableCollection<RoomModel> RoomsData { get; set; }
    public Page11()
    {
        InitializeComponent();
        RoomsData = new ObservableCollection<RoomModel>()
        {
            new RoomModel(){IsExpanded=true,ElementsVisible=true,Elements=new ObservableCollection<ElementModel>(){

                new ElementModel(){str="test 1"},new ElementModel(){str="test 12"},new ElementModel(){str="test 13"}}
            },
             new RoomModel(){IsExpanded=true,ElementsVisible=true,Elements=new ObservableCollection<ElementModel>(){

                new ElementModel(){str="test 2"},new ElementModel(){str="test 21"},new ElementModel(){str="test 23"}}
            },
              new RoomModel(){IsExpanded=true,ElementsVisible=true,Elements=new ObservableCollection<ElementModel>(){

                new ElementModel(){str="test 3"},new ElementModel(){str="test 31"},new ElementModel(){str="test 32"}}
            },
               new RoomModel(){IsExpanded=true,ElementsVisible=true,Elements=new ObservableCollection<ElementModel>(){

                new ElementModel(){str="test 4"},new ElementModel(){str="test 41"},new ElementModel(){str="test 43"}}
            }
        };

        this.BindingContext = this;
    }

    private void btn1_Clicked(object sender, EventArgs e)
    {
        RoomModel room = RoomsData.FirstOrDefault();
        room.ElementsVisible = false;
        collectionview.ItemsSource = RoomsData;
    }
}

public class RoomModel:ViewModelBase
{
    // Other properties omitted.. 
    private bool _IsExpanded;
    public bool IsExpanded
    {
        get { return _IsExpanded; }
        set
        {
            _IsExpanded = value;
            RaisePropertyChanged("IsExpanded");
        }
    }
    private bool _elementsVisible;
    public bool ElementsVisible
    {
        get { return _elementsVisible; }
        set
        {
            _elementsVisible = value;
            RaisePropertyChanged("ElementsVisible");
        }
    }
    public ObservableCollection<ElementModel> Elements { get; set; }
}
public class ElementModel 
{
    public string str { get; set; }
}

The ViewModelBase is class that implementing INotifyPropertyChanged.

 public class ViewModelBase : INotifyPropertyChanged
{
   
    public event PropertyChangedEventHandler PropertyChanged;
   
    public void RaisePropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
于 2021-04-27T06:29:16.667 回答