折叠所有扩展器,并默认扩展其中之一

瓦西姆·阿齐拉(Wassim AZIRAR)

我有多个扩展器,并且我一直在寻找一种方法,当其中一个扩展器扩展时,将所有其他扩展器折叠起来。我在这里找到了这个解决方案

XAML:

<StackPanel Name="StackPanel1">
    <StackPanel.Resources>
        <local:ExpanderToBooleanConverter x:Key="ExpanderToBooleanConverter" />
    </StackPanel.Resources>
    <Expander Header="Expander 1"
        IsExpanded="{Binding SelectedExpander, Mode=TwoWay, Converter={StaticResource ExpanderToBooleanConverter}, ConverterParameter=1}">
        <TextBlock>Expander 1</TextBlock>
    </Expander>
    <Expander Header="Expander 2"
        IsExpanded="{Binding SelectedExpander, Mode=TwoWay, Converter={StaticResource ExpanderToBooleanConverter}, ConverterParameter=2}">
        <TextBlock>Expander 2</TextBlock>
    </Expander>
    <Expander Header="Expander 3"
        IsExpanded="{Binding SelectedExpander, Mode=TwoWay, Converter={StaticResource ExpanderToBooleanConverter}, ConverterParameter=3}">
        <TextBlock>Expander 3</TextBlock>
    </Expander>
    <Expander Header="Expander 4"
        IsExpanded="{Binding SelectedExpander, Mode=TwoWay, Converter={StaticResource ExpanderToBooleanConverter}, ConverterParameter=4}">
        <TextBlock>Expander 4</TextBlock>
    </Expander>
</StackPanel>

转换器:

public class ExpanderToBooleanConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return (value == parameter);

        // I tried thoses too :
        return value != null && (value.ToString() == parameter.ToString());
        return value != null && (value.ToString().Equals(parameter.ToString()));
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return System.Convert.ToBoolean(value) ? parameter : null;
    }
}

ViewModel:

public class ExpanderListViewModel : INotifyPropertyChanged
{
    private Object _selectedExpander;

    public Object SelectedExpander
    {
        get { return _selectedExpander; } 
        set
        {
            if (_selectedExpander == value)
            {
                return;
            }

            _selectedExpander = value;
            OnPropertyChanged("SelectedExpander");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

初始化

var viewModel = new ExpanderListViewModel();
StackPanel1.DataContext = viewModel;
viewModel.SelectedExpander = 1;

// I tried this also
viewModel.SelectedExpander = "1";

它工作正常,但是现在我想在应用程序启动时扩展其中一个扩展器!

我已经尝试将值(1、2或3)放入SelectedExpander属性中,但是默认情况下,没有任何扩展器可以扩展!

如何将这种可能性添加到我的扩展器中?

纳米清洁

考虑如果在选择扩展器1时在扩展器2上调用UpdateSource会发生什么情况

  • ConvertBack会以当前IsExpanded值(false为扩展器2调用,并返回null
  • SelectedExpander已更新为null
  • Convert对于所有其他扩展器,都会调用,因为它已SelectedExpander更改,导致所有其他IsExpanded值也都设置false为。

当然,这不是正确的行为。因此,解决方案取决于源永远不会更新,除非用户实际切换了扩展器。

因此,我怀疑问题在于控件的初始化以某种方式触发了源代码更新。即使将扩展器1正确初始化为扩展,当在其他任何扩展器上刷新绑定时,它也会被重置。

为了ConvertBack正确起见,它需要注意其他扩展器:仅null所有扩展器都折叠时才返回但是,我看不到从转换器内部处理此问题的干净方法。也许最好的解决方案是使用单向绑定(no ConvertBack)并以这种方式或类似方式处理ExpandedCollapsed事件(_expanders所有扩展器控件的列表):

private void OnExpanderIsExpandedChanged(object sender, RoutedEventArgs e) {
    var selectedExpander = _expanders.FirstOrDefault(e => e.IsExpanded);
    if (selectedExpander == null) {
        viewmodel.SelectedExpander = null;
    } else {
        viewmodel.SelectedExpander = selectedExpander.Tag;
    }
}

在这种情况下,我使用Tag作为在视图模型中使用的标识符。

编辑:

为了以更“ MVVM”的方式解决它,您可以为每个扩展器收集一个视图模型,并将其绑定IsExpanded一个单独的属性

public class ExpanderViewModel {
    public bool IsSelected { get; set; }
    // todo INotifyPropertyChanged etc.
}

将集合存储在中,ExpanderListViewModel并在初始化时为每个处理程序添加PropertyChanged处理程序:

// in ExpanderListViewModel
foreach (var expanderViewModel in Expanders) {
    expanderViewModel.PropertyChanged += Expander_PropertyChanged;
}

...

private void Expander_PropertyChanged(object sender, PropertyChangedEventArgs e) {
    var thisExpander = (ExpanderViewModel)sender;
    if (e.PropertyName == "IsSelected") {
        if (thisExpander.IsSelected) {
            foreach (var otherExpander in Expanders.Except(new[] {thisExpander})) {
                otherExpander.IsSelected = false;
            }
        }
    }
}

然后将每个扩展器绑定到Expanders集合的不同项

<Expander Header="Expander 1" IsExpanded="{Binding Expanders[0].IsSelected}">
    <TextBlock>Expander 1</TextBlock>
</Expander>
<Expander Header="Expander 2" IsExpanded="{Binding Expanders[1].IsSelected}">
    <TextBlock>Expander 2</TextBlock>
</Expander>

(您可能还需要考虑定义一个自定义ItemsControl,以便根据该集合动态生成Expanders。)

在这种情况下,SelectedExpander将不再需要属性,但是可以通过以下方式实现:

private ExpanderViewModel _selectedExpander;
public ExpanderViewModel SelectedExpander
{
    get { return _selectedExpander; } 
    set
    {
        if (_selectedExpander == value)
        {
            return;
        }

        // deselect old expander
        if (_selectedExpander != null) {
           _selectedExpander.IsSelected = false;
        }

        _selectedExpander = value;

        // select new expander
        if (_selectedExpander != null) {
            _selectedExpander.IsSelected = true;
        }

        OnPropertyChanged("SelectedExpander");
    }
}

并将上述PropertyChanged处理程序更新为:

if (thisExpander.IsSelected) {
    ...
    SelectedExpander = thisExpander;
} else {
    SelectedExpander = null;
}

因此,现在这两行将是初始化第一个扩展器的等效方法:

viewModel.SelectedExpander = viewModel.Expanders[0];
viewModel.Expanders[0].IsSelected = true;

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

扩展一个扩展器也应该扩展所有其他扩展器

当所有内容折叠时隐藏扩展器

网格中的扩展器不会折叠

当所有子级都折叠或隐藏时,如何在分层数据模板中隐藏扩展器?

量角器 - 选择会选中所有选项,脚本无法正确选择其中之一

如何在窗口中以编程方式扩展所有扩展器

扩展器折叠动画不起作用

如果选择了其中之一,则过滤掉所有用户的条目

通过其中之一删除对象时,C ++将所有指针设置为null

我想显示所有行,但仅在高图表中显示其中之一的图例

打开其中之一后,所有通知均消失

如果其中之一存在异常,Async.Parallel是否取消所有作业?

如何使我的样式效果成为所有 ScrollViewers 但其中之一

查找所有出现并用PHP替换其中之一

当其中之一在 where 子句中时,SQL 显示所有行

当我单击其中之一时,所有通知都被隐藏

为什么当我更改其中之一时,所有日期选择器值都变为空?

如何显示所有 file_get_contents 中的所有数据并搜索其中之一

扩展器内部的DataGrid列标题绑定:折叠扩展器时找不到绑定源

WPF DataGrid扩展器中的分组行在右侧添加了额外的列,当所有扩展器都关闭时消失

当OS杀死其中之一时,是否会杀死同一进程中的所有服务?

Java是否检查“ &&”(和)运算符中的所有参数,即使其中之一为假?

如果其中之一会引发异常,如何在ThreadPoolExecutor中结束所有任务

为什么更改其中之一时所有Word.Range对象都会更改?

批处理文件以列出所有文件并将其中之一保存在循环中的变量中

扩展器与GridSplitter结合

WPF扩展器未扩展

Antd:是否可以将表格行扩展器移动到其中一个单元格内?

在包装器内定位 div,当内容溢出时,其中之一必须有 y 滚动条