Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/264.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.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
C# Wpf绑定桥_C#_Wpf - Fatal编程技术网

C# Wpf绑定桥

C# Wpf绑定桥,c#,wpf,C#,Wpf,我感觉这是wpf中的一个bug。让我知道你们对这件事的看法 为了保持一切简单,我在.NET4.0中制作了一个演示示例 我有一个ContentControl,其中内容绑定到数据,ContentTemplate包含一个绑定到内容的复选框 问题是,无论我多久单击一次复选框,Ok属性都不会为真 好像复选框没有将新值传递给ViewModel 看看这个: <Window.Resources> <DataTemplate x:Key="dataTemplate">

我感觉这是wpf中的一个bug。让我知道你们对这件事的看法

为了保持一切简单,我在.NET4.0中制作了一个演示示例

我有一个ContentControl,其中内容绑定到数据,ContentTemplate包含一个绑定到内容的复选框

问题是,无论我多久单击一次复选框,Ok属性都不会为真

好像复选框没有将新值传递给ViewModel

看看这个:

  <Window.Resources>
    <DataTemplate x:Key="dataTemplate">
      <CheckBox IsChecked="{Binding Path=., Mode=TwoWay}"/>
    </DataTemplate>
  </Window.Resources>

  <Grid>
    <ContentControl Content="{Binding Path=Ok, Mode=TwoWay}" ContentTemplate="{StaticResource dataTemplate}"/>
  </Grid>
有没有办法用ContentTemplate解决这个问题?

你可以这样做

<Window.Resources>
    <DataTemplate x:Key="dataTemplate">
      <CheckBox IsChecked="{Binding Path=Ok, Mode=TwoWay}"/>
    </DataTemplate>
</Window.Resources>

<Grid>
  <ContentControl Content="{Binding}" ContentTemplate="{StaticResource dataTemplate}"/>
</Grid>


在上面的示例中,我将内容绑定到视图模型本身,然后选中Ok属性的复选框。

问题在于
ContentControl
不会将其
DataContext
传递给内容

您需要手动设置
DataContext

<CheckBox DataContext="{Binding DataContext,RelativeSource={RelativeSource AncestorType={x:Type ContentControl}}}" IsChecked="{Binding Path=., Mode=TwoWay}"/>

您的问题是与值类型使用相关的常见问题。您正在将复选框数据绑定到一个基本的值类型(bool)(这是一件非常少见的事情)。由于
Binding.Source
的类型为
object
,因此您的布尔值将装箱到
对象中。对该装箱对象的任何更新都不会影响
ViewModel
上的原始属性

您可以通过将该布尔值替换为如下结构来测试该理论:

public struct MyStruct
{
    private bool _isChecked;
    public bool IsChecked
    {
        get { return _isChecked; }
        set { _isChecked = value; }
    }

    public ViewModel Parent { get; set; }
} 
并更改您的绑定:

<CheckBox IsChecked="{Binding Path=IsChecked, Mode=TwoWay}"/>
您应该看到父视图模型上的
MyStruct
属性根本不受数据绑定的影响


完整测试代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            ViewModel vm = new ViewModel();
            vm.Ok = new MyStruct { Parent = vm, IsChecked = false };
            this.DataContext = vm;
        }


    }

    public class ViewModel : INotifyPropertyChanged
    {
        private string txt;

        public string Txt
        {
            get { return txt; }
            set { txt = value; this.OnPropertyChanged("Txt"); }
        }

        private MyStruct ok;

        public MyStruct Ok
        {
            get { return ok; }
            set { ok = value; this.OnPropertyChanged("Ok"); }
        }


        private void OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }

    public struct MyStruct
    {
        private bool _isChecked;
        public bool IsChecked
        {
            get { return _isChecked; }
            set { _isChecked = value; }
        }

        public ViewModel Parent { get; set; }
    }
}
使用系统;
使用System.Collections.Generic;
使用系统组件模型;
使用System.Linq;
使用系统文本;
使用System.Windows;
使用System.Windows.Controls;
使用System.Windows.Data;
使用System.Windows.Documents;
使用System.Windows.Input;
使用System.Windows.Media;
使用System.Windows.Media.Imaging;
使用System.Windows.Navigation;
使用System.Windows.Shapes;
命名空间WpfApplication1
{
/// 
///MainWindow.xaml的交互逻辑
/// 
公共部分类主窗口:窗口
{
公共主窗口()
{
初始化组件();
ViewModel vm=新的ViewModel();
vm.Ok=newmystruct{Parent=vm,IsChecked=false};
this.DataContext=vm;
}
}
公共类视图模型:INotifyPropertyChanged
{
私有字符串txt;
公共字符串
{
获取{return txt;}
设置{txt=value;this.OnPropertyChanged(“txt”);}
}
私人MyStruct ok;
公共MyStruct Ok
{
获取{return ok;}
设置{ok=value;this.OnPropertyChanged(“ok”);}
}
私有void OnPropertyChanged(字符串propertyName)
{
if(this.PropertyChanged!=null)
{
this.PropertyChanged(this,newpropertychangedventargs(propertyName));
}
}
公共事件属性更改事件处理程序属性更改;
}
公共结构MyStruct
{
检查私人住宅;
公共场所被检查
{
获取{return\u已检查;}
设置{u isChecked=value;}
}
公共视图模型父项{get;set;}
}
}
xaml:


经过更多的研究(发布了一个不相关的答案,然后又删除了它)——并且受到了与Eren Ersönmez和Dev Hedgehog的讨论的推动——双向绑定
被检查=“{binding Path=,Mode=TwoWay}”无法工作的原因变得更加清楚了

(旁注:此答案不包含问题的解决方案。已提供了一个很好的解决方案。)

{Binding Path=,Source=SomeSource}
表示直接绑定到绑定源的绑定。等效的绑定语法是
{binding Source=SomeSource}

但是,绑定到绑定源本身的绑定不能是双向的。通过指定
{Binding Source=SomeSource,Mode=TwoWay}
尝试这样做将在运行时导致InvalidOperationException

另一方面,
{Binding Path=,Source=SomeSource,Mode=TwoWay}
不会产生异常,但它仍然不会为这种数据绑定启用双向绑定。相反,它只会愚弄绑定引擎的绑定验证/错误处理机制

这一点已经在其他与约束相关的问题的答案中找到并讨论过,例如由或的答案(如果不是他们的答案以及我与Eren Ersönmez的讨论,我可能仍然不知道这里发生了什么……)

这也意味着问题不是由于装箱值类型本身就是绑定源引起的,而是由于试图使用绑定路径
的双向绑定


为什么使用绑定路径进行双向绑定毫无意义

下面是一个小例子来说明这个问题。它还表明,问题不仅限于装箱值类型作为绑定源的情况,也不限于涉及DataContext的绑定

静态属性Demo.SourceString提供的字符串(引用类型)将用作以下XAML代码段中的绑定源:

<TextBox Text="{Binding Source={x:Static My:Demo.SourceString}, Mode=TwoWay}" />

(请注意,My:Demo.SourceString属性提供的对象是绑定源;属性本身是而不是绑定源。)

上述XAML将在运行时生成InvalidOperationException。 但是,使用等效的XAML:

<TextBox Text="{Binding Path=., Source={x:Static My:Demo.SourceString}, Mode=TwoWay}" />

在运行时不会产生异常,但绑定仍然不是有效的双向绑定。输入到文本框中的文本将不会升级回Demo.SourceString pr
<Window x:Class="WpfApplication1.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">
    <Window.Resources>
    <DataTemplate x:Key="dataTemplate">
      <CheckBox IsChecked="{Binding Path=IsChecked, Mode=TwoWay}"/>
    </DataTemplate>
  </Window.Resources>

  <Grid>
    <ContentControl Content="{Binding Path=Ok, Mode=TwoWay}" ContentTemplate="{StaticResource dataTemplate}"/>
  </Grid>
</Window>     
public class Demo
{
    public static string SourceString
    {
        get { return _ss; }
        set { _ss = value; }
    }
    private static string _ss = "Hello World!";
}
<TextBox Text="{Binding Source={x:Static My:Demo.SourceString}, Mode=TwoWay}" />
<TextBox Text="{Binding Path=., Source={x:Static My:Demo.SourceString}, Mode=TwoWay}" />