Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
WPF中的力约束_Wpf_Unit Testing_Data Binding - Fatal编程技术网

WPF中的力约束

WPF中的力约束,wpf,unit-testing,data-binding,Wpf,Unit Testing,Data Binding,我正在编写测试来检查XAML中指定的绑定元素的正确性。到目前为止,它们仍然有效,唯一的问题是我不知道如何正确地强制数据绑定。令人惊讶的是,仅仅在DataContext中设置某些内容是不够的,只有显示控件/窗口,绑定才会发生。请不要说我在写“单元测试”,我不想显示任何窗口 请看下面的代码: // This is main class in console application where I have all WPF references added public class Program {

我正在编写测试来检查XAML中指定的
绑定
元素的正确性。到目前为止,它们仍然有效,唯一的问题是我不知道如何正确地强制数据绑定。令人惊讶的是,仅仅在
DataContext
中设置某些内容是不够的,只有显示控件/窗口,绑定才会发生。请不要说我在写“单元测试”,我不想显示任何窗口

请看下面的代码:

// This is main class in console application where I have all WPF references added
public class Program
{
    [STAThread]
    public static void Main()
    {
        var view = new Window();
        BindingOperations.SetBinding(view, Window.TitleProperty, new Binding("Length"));
        view.DataContext = new int[5];
        //view.Show(); view.Close(); // <-- this is the code I'm trying not to write
        Console.WriteLine(view.Title);
    }
}
//这是控制台应用程序中的主类,我在其中添加了所有WPF引用
公共课程
{
[状态线程]
公共静态void Main()
{
var view=新窗口();
BindingOperations.SetBinding(视图,Window.TitleProperty,新绑定(“长度”);
view.DataContext=newint[5];

//view.Show();view.Close();//不确定,但类似的方法可能会奏效

view.GetBindingExpression(Window.TitleProperty).UpdateTarget();

我认为您应该首先设置DataContext,然后进行绑定,例如:

view.DataContext = new int[5];
BindingOperations.SetBinding(view, Window.TitleProperty, new Binding("Length"));

我不确定这是否是一般问题的真正解决方案,但它在这种情况下有效。

我不相信
窗口的绑定会在不调用
Show
ShowDialog
的情况下运行,因为这是它与UI消息循环/调度程序关联的唯一方式

您最好将其设置为尽可能不可见,可能使用扩展方法来清理:

public static void PokeWindowDispatcher(this Window window)
{
    window.WindowState = WindowState.Minimized;
    window.ShowInTaskbar = false;
    window.Visibility = Visibility.None;

    using (var wait = new ManualResetEvent())
    {
        Action<object, RoutedEventArgs> loaded = (sender, e) => wait.Set();
        window.Loaded += loaded;
        try
        {
            window.Show();
            wait.WaitOne();
        }
        finally
        {
            window.Loaded -= loaded;
            window.Close();
        }
    }
}
公共静态void PokeWindowDispatcher(此窗口)
{
window.WindowState=WindowState.Minimized;
window.ShowInTaskbar=false;
window.Visibility=Visibility.None;
使用(var wait=new ManualResetEvent())
{
加载的操作=(发送方,e)=>wait.Set();
window.Loaded+=已加载;
尝试
{
window.Show();
等等,等等;
}
最后
{
window.Loaded-=已加载;
window.Close();
}
}
}

我也遇到了同样的问题,从六个变量中我得到了一个想法。非常简单。 我在WinForms应用程序中使用WPF,所以我使用ElementHost控件在WinForms控件上托管WPF控件。要强制WinForms控件初始化,您只需读取句柄的值(实际上是Windows HWND),这将强制控件完全初始化自身,包括子ElementHost和所有WPF绑定工作。 我没有尝试对纯Wpf控件执行相同的操作。但是您可以轻松地使用ElementHost初始化Wpf控件,如下所示:

var el = new ElementHost();
var p = new TextBlock();
p.DataContext = new { Data = "1234" };
p.SetBinding(TextBlock.TextProperty, "Data");
el.Child = p;
var t = el.Handle;
Debug.Assert(p.Text == "1234");

PS:发现,如果您先设置DataContext,然后才强制创建句柄(就像我的示例一样),那么一切都会更好。但是,我认为,对于您来说,这已经是一个问题了,所以应该不是一个问题。

您是否尝试过使用IsDataBound

另外,请查看以下内容:

System.Windows.Interop.WindowInteropHelper helper=new System.Windows.Interop.WindowInteropHelper(view.EnsureHandle()


我的另一个问题是,为什么要对已经过技术测试的东西进行单元测试?顺便说一句,我不是在批评,只是想更好地理解一下。

如果您试图测试您的观点的正确性,我建议您测试您的观点:-)

为什么不从单元测试运行UI并编写代码,在更改数据后检查UI的内容呢

VS2010确实有GUI测试,或者您可以查看Snoop等工具的代码


编辑以下评论:

如果您只想测试一些简单的绑定,请尝试编写一个静态代码测试,该测试使用XAMLs上的视图模型和正则表达式上的反射作为生成后事件运行。在VM上添加属性或使用配置文件,以便您的测试将知道哪个视图接收哪个视图模型作为DataContext。比较视图模型中的属性名称和类型如果字符串不匹配,则抛出异常(从而导致生成失败)


如果绑定更复杂(转换器、多绑定等),那么实现起来可能会更复杂一些。

调度程序将使用DispatcherPriority.DataBind更新绑定-因此,如果您等待具有SystemIdle优先级的虚拟任务,则您可以确保任何挂起的数据绑定都已完成

  try
  {
    this.Dispatcher.Invoke(DispatcherPriority.SystemIdle, new Action(() => { }));
  }
  catch
  {
    // Cannot perfom this while Dispatcher in suspended mode
  }

这不会有帮助,因为在真实代码中,我不知道在
视图上设置了哪些绑定,请参见我的更新。它可以工作,但我无法在真实代码中执行。在真实代码中(请参见我的第一次更新)我收到一个包含所有绑定的
视图
。绑定是用XAML创建的,XAML作为构造函数中调用的
InitializeComponents
的一部分进行解析,因此在设置绑定之前无法获取
视图
。是否尝试调用View.UpdateLayout()或View.InvalidateVisual()?@Aaron,正在尝试,但没有帮助。@Snowbear您在标准WPF应用程序中尝试过这些不同的方法吗?@Snowbear测试视图是出了名的困难。为什么不在xUnit或您正在使用的任何测试框架中创建视图的实例,并根据将DataContext设置为g来验证控件是否具有预期值iven ViewModel?声明单元测试类似于控制台应用程序并不意味着什么……您正在测试视图,而不管您使用的是什么测试框架。@Snowbear如果您没有测试绑定中的值是否准确,那么您的测试范围很窄,您现在正在尝试测试.NET FW,这是没有意义的。B绑定可以在没有
Show
的情况下工作,您可以检查Gimno的方法。使用他的代码
绑定
可以工作,尽管我认为他的解决方案不适合我。您可以尝试使用
Dispatcher.PushFrame()推送一个新的
DispatcherFrame
,但我不相信如果没有为您的
窗口制作
HWND
,任何事情都会发生