c# - WPF - 交换 ContentControl(重新链接元素???)

标签 c# wpf binding controls

我正在开发一个自定义面板控件,我试图让它做的一件事就是在运行时交换它的内容。该控件有两种状态:最大化和正常。当用户单击控件上的按钮时,状态会切换。此控件有两个属性:MaximizedContent 和 MinimizedContent。当单击交换状态的按钮时,控件的 Content 属性需要在 MaximizedContent 和 MinimizedContent 之间交换。当 MaximizedContent 或 MinimizedContent 内部存在绑定(bind)时,就会出现问题。它们似乎不是“树”的一部分,因此绑定(bind)不起作用......至少这是我的理论。所以我的问题是如何使它们成为树的一部分?

这是一个简化的示例:

MainWindow.xaml

<Window x:Class="SwappingContentTest.MainWindow"
        Loaded="Window_Loaded"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:local="clr-namespace:SwappingContentTest"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <StackPanel  HorizontalAlignment="Left">
        <Button x:Name="swapContentButton"
                Click="swapContentButton_Click"
                Content="Swap Content" />

        <local:SwappableContentControl x:Name="swappableControl">
            <local:SwappableContentControl.MaximizedContent>
                <StackPanel>
                    <CheckBox x:Name="maximizedCheckBox"
                              Content="Maximized CheckBox" />
                    <Button x:Name="maximizedButton"
                            Content="Maximized Button"
                            IsEnabled="{Binding ElementName=maximizedCheckBox, Path=IsChecked}" />
                </StackPanel>
            </local:SwappableContentControl.MaximizedContent>

            <local:SwappableContentControl.MinimizedContent>
                <StackPanel>
                    <CheckBox x:Name="minimizedCheckBox"
                              Content="Minimized CheckBox" />
                    <Button x:Name="minimizedButton"
                            Content="Minimized Button"
                            IsEnabled="{Binding ElementName=minimizedCheckBox, Path=IsChecked}" />
                </StackPanel>
            </local:SwappableContentControl.MinimizedContent>
        </local:SwappableContentControl>

        <CheckBox x:Name="standardCheckBox"
                  Content="Standard CheckBox"
                  Margin="0,20,0,0"/>
        <Button x:Name="standardButton"
                Content="StandardButton"
                IsEnabled="{Binding ElementName=standardCheckBox, Path=IsChecked}" />
    </StackPanel>
</Window>

MainWindow.cs

namespace SwappingContentTest
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            swappableControl.SwapContent();
        }

        private void swapContentButton_Click(object sender, RoutedEventArgs e)
        {
            swappableControl.SwapContent();
        }
    }
}

SwappableContentControl.cs

namespace SwappingContentTest
{
    public class SwappableContentControl : ContentControl
    {
        public static readonly DependencyProperty MaximizedContentProperty = DependencyProperty.Register("MaximizedContent", typeof(object), typeof(SwappableContentControl));

        public static readonly DependencyProperty MinimizedContentProperty = DependencyProperty.Register("MinimizedContent", typeof(object), typeof(SwappableContentControl));

        public static readonly DependencyProperty StateProperty = DependencyProperty.Register("State", typeof(SwappableContentControlState), typeof(SwappableContentControl),
            new PropertyMetadata(new PropertyChangedCallback(StatePropertyCallback)));

        public static void StatePropertyCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            SwappableContentControl control = (SwappableContentControl)d;
            if ((SwappableContentControlState)e.NewValue == SwappableContentControlState.Maximized)
            {
                control.Content = control.MaximizedContent;
            }
            else
            {
                control.Content = control.MinimizedContent;
            }
        }

        public object MaximizedContent
        {
            get { return GetValue(MaximizedContentProperty); }
            set { SetValue(MaximizedContentProperty, value); }
        }


        public object MinimizedContent
        {
            get { return GetValue(MinimizedContentProperty); }
            set { SetValue(MinimizedContentProperty, value); }
        }


        public SwappableContentControlState State
        {
            get { return (SwappableContentControlState)GetValue(StateProperty); }
            set { SetValue(StateProperty, value); }
        }

        public void SwapContent()
        {
            if (State == SwappableContentControlState.Maximized)
            {
                State = SwappableContentControlState.Normal;
            }
            else
            {
                State = SwappableContentControlState.Maximized;
            }
        }
    }
}

这是该项目的链接: http://www.freewebs.com/thrash505/SwappingContentTest.zip

最佳答案

我建议不要交换内容本身,而是在控件中放置两个 ContentControl 实例并更改可见性。除了整体上更干净之外,这还将具有仅更新控件布局而不强制重建树的性能优势。它还意味着两个 ContentControl 始终保留在逻辑树中,使它们更容易在控件实现中引用并保持绑定(bind)正确更新。另外,您还可以获得以下好处:它们可以单独模板化,从而为良好的视觉状态更改打开大门。

关于c# - WPF - 交换 ContentControl(重新链接元素???),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1099530/

相关文章:

javascript - WebView2:通过 Javascript 代码在 C# 中设置对象属性

c# - TwoWay 集合绑定(bind)同步/锁定

wpf - 绑定(bind)到 WPF 中 TabControl 的 ItemsSource

wpf - 将 String[] 转换为 Expando 以在 WPF 中绑定(bind) DataGrid

c# - 为什么 GetMember(string) 返回 MemberInfo 数组?

c# - MEF:我应该把 CompositionContainer 放在哪里?

c# - 如何在 MahApps.Metro 中添加 AnimatedTabControl?

c# - 抛出异常 C# 进阶

c# - 如何在 ServiceStack.OrmLite 中使用 OnUpdate = "CASCADE"

c# - 如何动态更改 ResourceDictionary