[英]WPF TextBox Binding does not update with Drag and Drop
我有一个wpf项目,其中有一个绑定的文本框,其中AllowDrop
设置为true。 如果我直接在此文本框中键入内容并离开该框,则此文本框的bound属性会按预期更改。
但是,如果我创建放置事件并将文本框的文本值设置为文件名值,则文本框的绑定属性不会更改。 我必须单击进入文本框并从中跳出标签。
我一定会误解绑定属性应如何工作。 我的想法是,如果框的文本更改,那么它也应该更新绑定的属性。
就目前而言,我必须拥有更新属性的背后代码,而不是依赖于绑定。 以下是我创建的示例项目。
XAML:
<Window.DataContext>
<local:XmlFile x:Name="XmlFileInfo"/>
</Window.DataContext>
...
<StackPanel Orientation="Horizontal" Grid.Row="0">
<Label Content="XML File:"/>
<TextBox x:Name="xmlFilePath" Text="{Binding XMLFile}" Height="25" VerticalAlignment="Top" MinWidth="300" AllowDrop="True" PreviewDragOver="xmlFilePath_PreviewDragOver" Drop="xmlFilePath_Drop"/>
</StackPanel>
下面是我的视图模型
public class XmlFile
{
private string _xmlfile;
private string _xmlElementName;
public string XMLFile
{
get { return _xmlfile; }
set
{
if (value != _xmlfile)
{
_xmlfile = value;
_xmlElementName = SetElementNameFromFileName();
}
}
}
...
}
最后是我的XAML代码
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Exit_Click(object sender, RoutedEventArgs e)
{
Application.Current.Shutdown();
}
private void SetControlState()
{
FileTest.IsEnabled = false;
if (!string.IsNullOrEmpty(XmlFileInfo.XMLFile))
{
if(XmlFileInfo.IsValidXml(XmlFileInfo.XMLFile))
{
FileTest.IsEnabled = true;
}
}
}
private void xmlFilePath_PreviewDragOver(object sender, DragEventArgs e)
{
e.Handled = true;
}
private void xmlFilePath_Drop(object sender, DragEventArgs e)
{
var filenames = (string[])e.Data.GetData(DataFormats.FileDrop);
if (filenames == null) return;
var filename = filenames.FirstOrDefault();
if (filename == null) return;
//XmlFileInfo.XMLFile = filename; <-- This bypasses the binding
(sender as TextBox).Text = filename; // This should trigger updating binding
SetControlState(); //<-- enables a button control if file is valid
}
}
我尝试将绑定模式设置为双向,并且其他绑定设置未更改任何行为。 我想做的是弄清楚如何使放置功能发挥作用,就像手动键入框并离开框一样,而不必绕开绑定并直接设置属性。
使您的ViewModel实现INotifyPropertyChanged。 与其直接更改文本框的文本,不如更改viewModel中的fileName。 这样就可以了。
您还必须在XMLFile-Property的设置器中调用OnPropertyChanged
public class XmlFile : INotifyPropertyChanged
{
private string _xmlfile;
private string _xmlElementName;
public string XMLFile
{
get { return _xmlfile; }
set
{
if (value != _xmlfile)
{
_xmlfile = value;
_xmlElementName = SetElementNameFromFileName();
OnPropertyChanged(nameof(XMLFile); //this tells your UI to update
}
}
}
...
}
private void xmlFilePath_Drop(object sender, DragEventArgs e)
{
var filenames = (string[])e.Data.GetData(DataFormats.FileDrop);
if (filenames == null) return;
var filename = filenames.FirstOrDefault();
if (filename == null) return;
//XmlFileInfo.XMLFile = filename; <-- This bypasses the binding
var viewModel = (XmlFile)this.DataContext;
viewModel.XMLFile = filename;
SetControlState(); //<-- enables a button control if file is valid
}
您应该看看DataBinding是如何工作的。
您要寻找的是以下内容:
var textBox = sender as TextBox;
if (textBox == null)
return;
// Sets the value of the DependencyProperty without overwriting the value, this will also update the ViewModel/XmlFile that TextBox is bound to.
textBox.SetCurrentValue(TextBox.TextProperty, "My Test Value");
您还可以通过以下方式强制绑定更新目标(XmlFile):
var textBinding = textBox.GetBindingExpression(TextBox.TextProperty);
// This will force update the target (rather than wait until control loses focus)
textBinding?.UpdateTarget();
我遇到一种情况,需要用文件路径填充多个文本框。 我使用了akjoshi中提出的想法: 从View更新ViewModel 。 我通过以下方式实现了它:
private void Text_Drop(object sender, DragEventArgs e)
{
TextBox temp = sender as TextBox;
if(temp == null)
return;
string[] tempArray = (string[])e.Data.GetData(DataFormats.FileDrop, false);
temp.Text = tempArray[0];
sender = temp;
BindingExpression bind = BindingOperations.GetBindingExpression(temp, TextBox.TextProperty);
bind.UpdateSource();
}
希望这可以帮助!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.