XAML WPF根据可观察集合中的项更改可见性

zf2sa74q  于 2022-12-07  发布在  其他
关注(0)|答案(3)|浏览(177)

I have the Following Collection: ObservableCollection Files
CheckedFileObject包含一个FileObject和一个bool isChecked。现在当用户选择一个文件时,该文件的isChecked值将变为true。
如果至少有一个CheckedFileObject包含IsChecked = true,我想使删除按钮可见。
所以我的问题是,是否可以根据ObservableCollection中的项切换可见性,以及如何切换?我不在乎有多少项,但如果选中了一项,按钮应该是可见的。
可能是这样的:

Visibility="{Binding Files[i].IsChecked, Mode=OneWay, Converter={StaticResource BooleanAndToVisibilityConverter}}"

或者可能是binding将ObservablCollection绑定到视图模型中的一个bool,该bool通过如下方式更新:

var isVisible = Files.Any(x => x.IsChecked == true);

当收藏品改变的时候,这可能吗

u59ebvdq

u59ebvdq1#

你可以从ListCollectionView类和changeButton中获得项目跟踪的特性。基于集合视图中项目计数的可见性:

public ObservableCollection<CheckedFileObject> Files { get; } = new ObservableCollection<CheckedFileObject>();

private ICollectionView _filteredFiles;
public ICollectionView FilteredFiles 
{
    get
    {
        if (_filteredFiles == null)
        {
            _filteredFiles = new ListCollectionView(Files)
            {
                IsLiveFiltering = true,
                LiveFilteringProperties = { nameof(CheckedFileObject.IsChecked) },
                Filter = (o) => o is CheckedFileObject file && file.IsChecked
            };
        }
        return _filteredFiles;
    }
}

显示原始集合中的项。按钮绑定到筛选的集合:

<ItemsControl ItemsSource="{Binding Files}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <CheckBox IsChecked="{Binding Path=IsChecked}"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

<Button Content="Delete">
    <Button.Style>
        <Style TargetType="Button">
            <Style.Triggers>
                <DataTrigger Binding="{Binding Path=FilteredFiles.Count}" Value="0">
                    <Setter Property="Visibility" Value="Collapsed"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Button.Style>
</Button>

CheckedFileObject类必须具有属性更改通知(实现INotifyPropertyChanged):

public class CheckedFileObject : INotifyPropertyChanged
{
    private bool isChecked;

    public bool IsChecked 
    { 
        get => isChecked; 
        set 
        {
            isChecked = value; 
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsChecked)));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}
rm5edbpk

rm5edbpk2#

您可以尝试使用如下所示的转换器:

public class CheckedFileObjectToVisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value is ObservableCollection<CheckedFileObject> files)
        {
            if (files.Any(x => x.IsChecked == true))
                return Visibility.Visible;
        }
        return Visibility.Collapsed;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

请注意,如果在视图中多次重复此控件,则可能需要改进此代码的性能。

nlejzf6q

nlejzf6q3#

public class SomeVm
{
    public SomeVm()
    {
        Files = new ObservableCollection<CheckedFileObject>();
        Files.CollectionChanged += Files_CollectionChanged;

        StartCommand = new DelegateCommand(ExecuteStart, () => Files.Any(f => f.IsChecked));
    }

    private void Files_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        if (e.Action == NotifyCollectionChangedAction.Remove || e.Action == NotifyCollectionChangedAction.Replace)
        {
            foreach (INotifyPropertyChanged checkedFileObject in e.OldItems)
            {
                checkedFileObject.PropertyChanged -= FileObject_PropertyChanged;
            }
        }
        if (e.Action == NotifyCollectionChangedAction.Add || e.Action == NotifyCollectionChangedAction.Replace)
        {
            foreach (INotifyPropertyChanged checkedFileObject in e.NewItems)
            {
                checkedFileObject.PropertyChanged += FileObject_PropertyChanged;
            }
        }
    }

    private void FileObject_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == nameof(CheckedFileObject.IsChecked))
            StartCommand.RaiseCanExecuteChanged();
    }

    public ObservableCollection<CheckedFileObject> Files { get; }
    public DelegateCommand StartCommand { get; }

    private void ExecuteStart() { throw new NotImplementedException(); }
}

public class CheckedFileObject : ObservableObject
{
    public bool IsChecked { get; set; }
    public FileInfo FileInfo { get; }
}

您也可以使用多重选择来实现它

相关问题