【问题标题】:Expander Control - UWP扩展器控制 - UWP
【发布时间】:2020-10-02 17:18:00
【问题描述】:

我的 UWP 应用中有一个扩展器控件,代码如下:

<Expander
     Header="A"
     IsExpanded =" True">
     <TextBlock
       Text="Content in A"/>
</Expander>
<Expander
     Header="B">
     <TextBlock
       Text="Content in B"/>
</Expander>

目前扩展器A默认展开,B关闭。但是,当我展开 B 时,A 也打开了。我想要这样的行为,如果我扩展一个,另一个关闭,反之亦然。关于如何以 MVVM 方式实现这一目标的任何建议?我需要在这里使用转换器吗?我查看了Collapse all the expanders and expand one of them by default,但大多数解决方案恰好是修改后面的代码。如果我在 Main.xaml 中有一个 XAML 代码并且我有一个相应的 MainPageViewModel.cs,我如何实现相同的效果?

【问题讨论】:

    标签: xaml uwp uwp-xaml


    【解决方案1】:

    我希望如果我展开一个,另一个关闭,反之亦然。

    对于这种情况,您可以使用OppositConverter 使另一个扩展器在上一个打开时关闭。

    public class OppositConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, string language)
        {
      
            return !(bool)value;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, string language)
        {
            return !(bool)value;
        }
    }
    public class MainPageViewModel : INotifyPropertyChanged
    {
        public MainPageViewModel()
        {
    
        }
        private bool _isExpend;
    
        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged([CallerMemberName] string name = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }
        public bool IsExpend
        {
            get
            {
                return _isExpend;
            }
            set
            {
                _isExpend = value;
                OnPropertyChanged();
            }
        }
    }
    

    用法

    <Page.DataContext>
        <local:MainPageViewModel x:Name="ViewModel" />
    </Page.DataContext>
    <Page.Resources>
        <local:OppositConverter x:Key="OppositConverter" />
    </Page.Resources>
    <StackPanel>
        <controls:Expander
            x:Name="Expander1"
            Margin="0,0,0,10"
            VerticalAlignment="Top"
            HorizontalContentAlignment="Stretch"
            ExpandDirection="Down"
            Header="This is the header - expander 1"
            IsExpanded="{Binding IsExpend, Mode=TwoWay}">
            <Grid>
                <TextBlock
                    HorizontalAlignment="Center"
                    VerticalAlignment="Center"
                    Text="This is the expanded content"
                    TextWrapping="Wrap" />
            </Grid>
        </controls:Expander>
        <controls:Expander
            x:Name="Expander2"
            Margin="0,0,0,10"
            VerticalAlignment="Top"
            HorizontalContentAlignment="Stretch"
            ExpandDirection="Down"
            Header="This is the header - expander 2"
            IsExpanded="{Binding IsExpend, Converter={StaticResource OppositConverter}, Mode=TwoWay}">
            <Grid>
                <TextBlock
                    HorizontalAlignment="Center"
                    VerticalAlignment="Center"
                    Text="This is the expanded content"
                    TextWrapping="Wrap" />
            </Grid>
        </controls:Expander>     
    </StackPanel>
    

    【讨论】:

    • 感谢 Nico 提供的这个示例。我将上面的代码修改如下以获得所需的输出。在公共类 MainPageViewModel 中,我使用了 set { isExpend=value; RaisePropertyChanged(nameof(isExpend))} 而不是 onPropertyChanged 方法。我还修改了 xaml 文件,使第一个扩展器使用转换器而不是第二个。在 RaisePropertyChanged 上使用该方法有什么区别?什么时候在这里调用 ConvertBack ?
    • RaisePropertyChangedOnPropertyChanged 没有区别。当属性更改时,它们都可以通知 ui 更新。唯一的区别是OnPropertyChanged会自动获取属性名。
    • ConvertBack 在将目标数据传递给源对象之前对其进行修改。此方法仅在 TwoWay 绑定中调用。
    • 感谢您的解释。我可以帮助理解这段代码的流程吗?什么时候在这里调用转换代码?当第一个展开器打开,第二个展开器收起时,用户点击打开第二个展开器,第一个展开器如何收起?
    • 是的,两个扩展器绑定了相同的IsExpend 属性。但第二个使用转换器得到反对。当我们点击第二个时,IsExpend 将变为 true,并且此行为将调用 ConvertBack 方法返回 false。而此时IsExpend值(false)的变化会影响第一个扩展器。
    猜你喜欢
    • 1970-01-01
    • 2012-01-05
    • 2015-01-22
    • 1970-01-01
    • 1970-01-01
    • 2014-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多