Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/334.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# 使用XElement的WPF动态属性绑定无法正常工作_C#_Wpf_Xaml_Linq To Xml - Fatal编程技术网

C# 使用XElement的WPF动态属性绑定无法正常工作

C# 使用XElement的WPF动态属性绑定无法正常工作,c#,wpf,xaml,linq-to-xml,C#,Wpf,Xaml,Linq To Xml,我想我在WPF中发现了一个bug,或者我对动态属性和绑定一无所知 在下面的代码中,如果XDocument不存在,我想在编辑时向XDocument添加一个节点。为此,我创建了一个附加属性,用于监视TextBox上的文本更改事件,若用户在TextBox中键入了某些内容,我将检查XDocument中是否存在元素,若不存在,则将其添加 (对于explainp1和p2是XElement对象。) 如果我只使用p1,一切正常。当我键入第一个字符事件时,检查节点不存在,并在我键入下一个字符时将其添加到XDocu

我想我在WPF中发现了一个bug,或者我对动态属性和绑定一无所知

在下面的代码中,如果XDocument不存在,我想在编辑时向XDocument添加一个节点。为此,我创建了一个附加属性,用于监视TextBox上的文本更改事件,若用户在TextBox中键入了某些内容,我将检查XDocument中是否存在元素,若不存在,则将其添加

(对于explain
p1
p2
是XElement对象。)

如果我只使用
p1
,一切正常。当我键入第一个字符事件时,检查节点不存在,并在我键入下一个字符时将其添加到XDocument(键入的字符消失,但这并不重要)节点是否正确更新

现在,如果我使用
p2
并在文本框中键入字符,则节点正在创建(字符不会消失),当我键入下一个字符时,节点不会更新。那不能正常工作

我观察到,在xaml中,我对
第1行
第2行
进行了重新排序,
第2行
位于
第1行

使用System.Windows;
使用System.Windows.Controls;
使用System.Xml.Linq;
名称空间WpfApp13
{
公共静态类TextChangedAction
{
#区域AddNodeIfNotExists
公共静态字符串GetAddNodeIfNotExists(DependencyObject obj)
{
返回(字符串)obj.GetValue(AddNodeIfNotExistsProperty);
}
公共静态void SetAddNodeIfNotExists(DependencyObject对象,字符串值)
{
对象设置值(AddNodeIfNotExistsProperty,value);
}
公共静态只读从属属性AddNodeIfNotExistsProperty=
DependencyProperty.RegisterAttached(“AddNodeIfNotExists”、typeof(string)、typeof(TextChangedAction)、new PropertyMetadata(null,AddNodeIfNotExistsPropertyChanged));
私有静态void AddNodeIfNotExistsPropertyChanged(DependencyObject d,DependencyPropertyChangedEventArgs e)
{
如果(d是文本框文本框)
{
textBox.TextChanged+=textBox\u TextChanged;
}
}
私有静态无效文本框\u TextChanged(对象发送者,textchangedventargs e)
{
var textBox=(textBox)发送方;
var parentNode=(XElement)textBox.DataContext;
var nodeName=GetAddNodeIfNotExists(文本框);
if(parentNode.Element(nodeName)==null)
{
添加(新的XElement(nodeName));
//取消一行吼叫,一切正常
//textBox.GetBindingExpression(textBox.TextProperty).UpdateTarget();
}
}
#端区
}
}

因此,我认为这更像是一个边缘案例,而不是一个bug。 实际上,一方面有一个从TextBox到XElement的绑定,另一方面有一个TextChanged事件,从同一个TextBox触发并创建同一个XElement

我不认为我们能说出应该按什么顺序发生,或者它是否能发生

例如,尝试在文本框的绑定中添加
Mode=TwoWay
。如果将文本添加到
p2
,您会注意到问题仍然存在,但一旦将文本添加到
p1
p2
就会按预期工作

我认为最简单的解决方案是在您的特定情况下忘记绑定,只需使用代码隐藏事件

将此代码添加到MainWindow.xaml.cs(或其名称):

并修改文本框,将其
标记
属性设置为相应的XElement名称:

<!--ROW P1-->
<TextBlock Grid.Column="0" Grid.Row="0" Text="p1:" />
<TextBox Grid.Column="1" Grid.Row="0" Tag="p1" TextChanged="TextBox_TextChanged"/>
<!--ROW P2-->
<TextBlock Grid.Column="0" Grid.Row="1" Text="p2:" />
<TextBox Grid.Column="1" Grid.Row="1" Tag="p2" TextChanged="TextBox_TextChanged" />


我必须补充一点,这是一个值得研究的有趣课题;我试着使用一个转换器,一个多转换器,但最终还是做不到一些干净的事情。我认为MVVM将是以适当的方式处理它的最佳方式。我打赌你可以将整个过程作为附加行为来编写。但撇开纳诺诡辩不谈,我也一直在讨论这个问题,对于OP的方法为什么会出现这样的错误,我也同样感到茫然——这与它的顺序相关的直觉是一样的。MVVM解决方案可能需要相当多的工作,这取决于OP希望UI能够修改XML的程度。但那就是我要做的。我知道如何去做这件事。我不知道为什么一次有效,另一次无效。我应该向微软报告一个bug吗?@siwydym67如果你真的想,你可以试试,但正如我所说,这是一个边缘案例。您无法预先确定操作的顺序,因此即使您现在可以修复它,谁知道它在未来的.Net版本中是否仍然有效。我不认为它是一个真正的bug。
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
    TextBox tb = sender as TextBox;
    XElement parentNode = tb.DataContext as XElement;

    string nodeName = tb.Tag as string;

    XElement node = parentNode.Element(nodeName);
    if (node == null)
    {
        node = new XElement(nodeName);
        parentNode.Add(node);
    }

    node.Value = tb.Text
}
<!--ROW P1-->
<TextBlock Grid.Column="0" Grid.Row="0" Text="p1:" />
<TextBox Grid.Column="1" Grid.Row="0" Tag="p1" TextChanged="TextBox_TextChanged"/>
<!--ROW P2-->
<TextBlock Grid.Column="0" Grid.Row="1" Text="p2:" />
<TextBox Grid.Column="1" Grid.Row="1" Tag="p2" TextChanged="TextBox_TextChanged" />