我遇到了错误。这是场景:
任何人都可以帮我解决这个问题。我很乐意上传整个VS解决方案,如果这有帮助(它不是那么大)。我真的很想了解这项技术的缺陷。我现在似乎正在与技术作斗争,而不是利用它的力量。
干杯
答案 0 :(得分:0)
我对您描述的场景进行了最简单的实现,并且对我来说没有错误。我会为它发布代码。请指出代码中的差异所在。
<Window x:Class="LogicalChildException.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<DockPanel>
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal">
<Button Name="ChangeUserControl" Click="ChangeUserControl_Click">Change UserControl</Button>
</StackPanel>
<ScrollViewer Content="{Binding ActiveFunction}">
</ScrollViewer>
</DockPanel>
</Window>
<UserControl x:Class="LogicalChildException.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<TextBlock Height="500" FontSize="30">
UserControl One
</TextBlock>
</Grid>
</UserControl>
<UserControl x:Class="LogicalChildException.UserControl2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<TextBlock Height="300" FontSize="10">
UserControl Two
</TextBlock>
</Grid>
</UserControl>
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
namespace LogicalChildException
{
public partial class MainWindow : Window,INotifyPropertyChanged
{
public MainWindow()
{
InitializeComponent();
ActiveFunction = new UserControl1();
DataContext = this;
}
private void ChangeUserControl_Click(object sender, RoutedEventArgs e)
{
if (ActiveFunction is UserControl1)
ActiveFunction = new UserControl2();
else
ActiveFunction = new UserControl1();
}
private UserControl _activeFunction;
public UserControl ActiveFunction
{
get { return _activeFunction; }
set
{
_activeFunction = value;
if(PropertyChanged!=null)
PropertyChanged(this,new PropertyChangedEventArgs("ActiveFunction"));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
答案 1 :(得分:0)
我进一步调查,发现问题出在UserCtrl1中包含的控件上。我完全迷失了。所以,最简单的方法是让我在线发布我的VS解决方案。它比我试图解释一些我不理解的东西(对你来说也更容易)要简单得多。 Click here to download
可以非常轻松地重新创建异常。运行解决方案(VS 2010),单击“进度”按钮。然后单击“项目”按钮(返回应用程序首次启动时加载的原始用户控件)。
请注意,UserCtrl1实际上是 NewWork ,而UserCtrl2是 ProgressView 。
答案 2 :(得分:0)
您收到该错误的原因是您将ScrollViewer的内容设置为UserControl。通过这样做,您将UserCtrl1(UserControl)的父级设置为ScrollViewer。如果您不能将两个子项设置为ScrollViewer,那么当您尝试将UserCtrl2设置为ActiveFunction时会发生这种情况。你真正应该做的是过度利用WPF中ViewModels和DataTemplates的强大功能。
从您发布的代码我改变它以使用更多的MVVM方法。
这是MainWindow。
<Window x:Class="LogicalChildException.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:LogicalChildException"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<ResourceDictionary>
<DataTemplate DataType="{x:Type local:UserControl1ViewModel}">
<local:UserControl1 />
</DataTemplate>
<DataTemplate DataType="{x:Type local:UserControl2ViewModel}">
<local:UserControl2 />
</DataTemplate>
</ResourceDictionary>
</Window.Resources>
<DockPanel>
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal">
<Button Command="{Binding SwitchCommand}">Change UserControl</Button>
</StackPanel>
<ScrollViewer Content="{Binding ActiveFunction}">
</ScrollViewer>
</DockPanel>
以下是MainWindow.xaml.cs背后的代码。基本上我在这里做的是我将此视图的DataContext设置为viewmodel。这不是最好的方法,因为你是硬编码的东西。更好的方法是利用数据模板并让WPF处理它。
using System.Windows;
namespace LogicalChildException
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new MainViewModel();
}
}
}
以下是ViewModels的代码。我使用了从这里http://www.wpftutorial.net/DelegateCommand.html找到的DelegateCommand的想法。 UserControl1ViewModel和UserControl2ViewModel只是虚拟对象,但您可以使它们实现INotifyPropertyChanged,然后将其用于数据模板中的绑定。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Windows.Input;
namespace LogicalChildException
{
public class DelegateCommand : ICommand
{
private readonly Predicate<object> _canExecute;
private readonly Action<object> _execute;
public event EventHandler CanExecuteChanged;
public DelegateCommand(Action<object> execute)
: this(execute, null)
{
}
public DelegateCommand(Action<object> execute,
Predicate<object> canExecute)
{
_execute = execute;
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
if (_canExecute == null)
{
return true;
}
return _canExecute(parameter);
}
public void Execute(object parameter)
{
_execute(parameter);
}
public void RaiseCanExecuteChanged()
{
if (CanExecuteChanged != null)
{
CanExecuteChanged(this, EventArgs.Empty);
}
}
}
public class MainViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private ICommand _switchCommand;
private object _activeFunction;
private object _userControl1;
private object _userControl2;
public MainViewModel()
{
_switchCommand = new DelegateCommand(OnSwitch);
_userControl1 = new UserControl1ViewModel();
_userControl2 = new UserControl2ViewModel();
ActiveFunction = _userControl1;
}
public ICommand SwitchCommand
{
get
{
return _switchCommand;
}
}
public object ActiveFunction
{
get
{
return _activeFunction;
}
set
{
if (_activeFunction != value)
{
_activeFunction = value;
OnPropertyChanged("ActiveFunction");
}
}
}
private void OnSwitch(object obj)
{
// do logic for switching "usercontrols" here
if (ActiveFunction == null)
{
// if null, just set it to control 1
ActiveFunction = _userControl1;
}
else
{
ActiveFunction = (ActiveFunction is UserControl1ViewModel) ? _userControl2 : _userControl1;
}
}
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
public class UserControl1ViewModel
{
}
public class UserControl2ViewModel
{
}
}
这里有许多方面可以改进,以便在MVVM世界中更清洁,但这可以帮助您解决当前的问题。