替换UserControl的属性

5

我在主UserControl中放置了两个User Control

只有其中一个应该在主要位置上。

当您更改ViewModel中的某些属性时,我会像这样更改它们:

<UserControl>
    <ContentControl>
        <ContentControl.Style>
            <Style TargetType="{x:Type ContentControl}">
                <Setter Property="Content">
                    <Setter.Value>
                        <local:UserControl1/>
                    </Setter.Value>
                </Setter>
                <Style.Triggers>
                    <DataTrigger Binding="{Binding IsTwo}" Value="True">
                        <Setter Property="Content">
                            <Setter.Value>
                                <local:UserControl2/>
                            </Setter.Value>
                        </Setter>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </ContentControl.Style>
    </ContentControl>
</UserControl>

当我将属性更改为False时,它可以毫无问题地转到UserControl1,但当我将其更改为True时,显示会出现问题,只有当我在屏幕之间移动时才适合,作为一个临时解决方案,我创建了每次UserControl从1 到2更改时运行的事件。当该事件运行时,我删除主UserControl并重新创建。 但我的问题是,为什么切换到一时我不需要重新创建,而切换到二时可能需要呢? 请勿提供任何解决方法(我已经自己做过了),我想解释为什么会发生这种情况,这才是我感兴趣的。

“显示问题”是什么意思?你能展示一下截图吗? - Dan Puzey
@DanPuzey,我的意图是:它没有像应该显示的那样在屏幕上显示,看起来它卡在了之前的用户控件(UserControl1)上,我也无法再访问它了(单击用户控件中的按钮不会有任何反应,无论是第一个还是第二个)。 - Hodaya Shalom
如果你最小化并恢复窗口,哪个控件会显示?我在想,如果由于某种原因你的内容正在改变,但窗口没有重新渲染。 - Dan Puzey
@DanPuzey,听起来很有趣,因为当我从第二个移动到第一个时,是的,它会正确地显示出来,但我会检查一下。 - Hodaya Shalom
1
尝试切换您的用户控件(首先显示UserControl2),它在启动时是否正确显示?您的XAML对我来说很好,因此问题很可能出在其他地方。 - Mike Fuchs
值得检查您的图形驱动程序 - WPF 使用硬件渲染,过时的驱动程序有时会导致渲染问题。 - Dan Puzey
1个回答

5

你的WPF没问题,我无法重现你的问题。开始一个新的WPF应用程序,并将以下内容倾入其中:然后用你的用户控件替换它(记得如果你想将其绑定到特定的东西,则可能需要在模板中绑定用户控件)

ViewModel.cs:

public class ViewModel : INotifyPropertyChanged
{
    private bool _isTwo;

    public bool IsTwo
    {
        get { return _isTwo; }
        set
        {
            _isTwo = value;
            OnPropertyChanged("IsTwo");
        }
    }

    public ICommand Switch
    {
        get { return new RelayCommand((_) => { IsTwo = !IsTwo; }, (_) => true); }
    }

    public event PropertyChangedEventHandler PropertyChanged;

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

public class RelayCommand : ICommand
{
    private readonly Action<object> _action;
    private readonly Func<object, bool> _predicate;

    public RelayCommand(Action<object> action, Func<object, bool> predicate)
    {
        _action = action;
        _predicate = predicate;
    }

    public bool CanExecute(object parameter)
    {
        return _predicate(parameter);
    }

    public void Execute(object parameter)
    {
        _action(parameter);
    }

    public event EventHandler CanExecuteChanged;
}

主窗口

<Window.DataContext>
    <local:ViewModel/>
</Window.DataContext>

<DockPanel>
    <Button DockPanel.Dock="Top" Command="{Binding Switch}"> Switch </Button>
    <UserControl>
        <ContentControl >
            <ContentControl.Style>
                <Style TargetType="{x:Type ContentControl}">
                    <Setter Property="Content">
                        <Setter.Value>
                            <local:UserControl1 DataContext="{Binding UserControl1ViewModel}"/>
                        </Setter.Value>
                    </Setter>
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding IsTwo}" Value="True">
                            <Setter Property="Content">
                                <Setter.Value>
                                    <local:UserControl2/>
                                </Setter.Value>
                            </Setter>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </ContentControl.Style>
        </ContentControl>
        </UserControl>
</DockPanel>

创建两个新的(空的)UserControl并设置两种不同的颜色:

关闭 开启

将其中一个替换为出现问题的用户控件。如果您遇到布局问题,很可能是因为您的用户控件正在尝试调整大小,或者需要将它们放在更好的容器中。我将以上内容放入DockPanel中。这通常非常擅长将控件扩展到可用空间。
[编辑]
因此,如果您想知道什么时间创建了什么,请在用户控件的ctor中放置一些消息框。
public UserControl1()
{
    InitializeComponent();

    MessageBox.Show("Created UserControl1");
}

public UserControl2()
{
    InitializeComponent();

    MessageBox.Show("Created UserControl2");
}

对于我来说,它们两个都是在应用程序启动时创建的,即UserControl2还不可见,但已经被创建。人们会认为它在数据触发器切换之前不会绑定; 但如果你在用户控件中使用了一些代码后台,那可能会破坏WPF。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接