簡體   English   中英

WPF文本框綁定不會通過拖放更新

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM