【问题标题】:UserControl Property Binding not Updating the DataContextUserControl 属性绑定不更新 DataContext
【发布时间】:2014-03-17 02:41:46
【问题描述】:

我创建了这个简单的可重用控件来浏览文件。

然后我做了一个模型并实现了 OnPropertyChanged 并使用了 MainWindow 中的控件。

当我单击 UserControl 中的 Browse 按钮​​时,DependencyProperty "FilePath" 已正确设置(并且文本框获取路径字符串),但模型似乎不起作用。

附加信息:如果我使用普通文本框而不是 UserControl 广告,我会这样做

<TextBox Text="{Binding InputFile}"/>

当我在框中输入内容时,模型会正确更新。 如果我在 UserControl 中手动输入一些内容(而不是通过浏览按钮填充它,它无论如何都不起作用)

这是 UserControl 的代码,控件内的属性设置正确:

public partial class FileBrowserTextBox : UserControl
{
    public FileBrowserTextBox()
    {
        InitializeComponent();
    }

    // FilePath
    public static readonly DependencyProperty FilePathProperty =
        DependencyProperty.Register("FilePath", typeof(string), typeof(FileBrowserTextBox), new FrameworkPropertyMetadata(string.Empty, new PropertyChangedCallback(OnFilePathPropertyChanged)));

    public string FilePath
    {
        get { return (string)GetValue(FilePathProperty); }
        set { SetValue(FilePathProperty, value); }
    }
    static void OnFilePathPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
    {
        var obj = o as FileBrowserTextBox;
        if (obj == null)
            return;
    }
    private void BrowseButton_Click(object sender, RoutedEventArgs e)
    {
        // Create OpenFileDialog 
        Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
        // Set filter for file extension and default file extension 
        dlg.DefaultExt = ".txt";
        dlg.Filter = "TXT Files (*.txt)|*.txt|All Files (*.*)|*.*";
        // Display OpenFileDialog by calling ShowDialog method 
        Nullable<bool> result = dlg.ShowDialog();
        // Get the selected file name and display in a TextBox 
        if (result == true)
        {
            // Open document 
            string filename = dlg.FileName;
            FilePath = filename; // this works and updates the textbox
        }
    }
}

这是 XAML 的摘录:

<UserControl x:Class="DrumMapConverter.FileBrowserTextBox">
        ...
        <Button Content=" ... " Click="BrowseButton_Click"/>
        <TextBox Name="txtFilepath" Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Path=FilePath}"/>
        ...
</UserControl>

这是我与 INotifyPropertyChanged 一起使用的模型:

public class DrumMapConverterDataModel :INotifyPropertyChanged
{
    public string InputFile
    {
        get { return inputFile; }
        set
        {
            inputFile = value;
            OnPropertyChanged("InputFile");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    // Create the OnPropertyChanged method to raise the event 
    protected void OnPropertyChanged(string name)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }

    private string inputFile;
}

这是 MainWindow 类

public partial class MainWindow : Window
{
    private DrumMapConverterDataModel model;
    public MainWindow()
    {
        InitializeComponent();
        model = new DrumMapConverterDataModel();
        DataContext = model;
    }

    private void Button_Click_1(object sender, RoutedEventArgs e)
    {
        MessageBox.Show(model.InputFile); // if i break here the model has no data changed (InputFile is null)
    }
}

这就是我使用 2 个控件的方式(2 个示例都不起作用):

<cust:FileBrowserTextBox  Label="Input File" FilePath="{Binding InputFile}"/>
<cust:FileBrowserTextBox  Label="Input File" FilePath="{Binding Path=InputFile, Mode=TwoWay, 
                       RelativeSource={RelativeSource FindAncestor, 
                           AncestorType=Window}}"/>

任何帮助将不胜感激。

更新和解决方案:

正如@AnatoliyNikolaev(感谢他对UpdareSourceTrigger 的解释)和用户控件中的@Karuppasamy 所建议的那样(明确使用UpdateSourceTrigger,因为它是一个文本框):

<TextBox Grid.Column="2" Name="txtFilepath" Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Path=FilePath, UpdateSourceTrigger=PropertyChanged}"/>

那么DependencyProperty可以是这样的(注意BindsTwoWayByDefault):

public static readonly DependencyProperty FilePathProperty =
    DependencyProperty.Register("FilePath", typeof(string), typeof(FileBrowserTextBox), new FrameworkPropertyMetadata(string.Empty, new PropertyChangedCallback(OnFilePathPropertyChanged)) { BindsTwoWayByDefault = true });

所以最后在 MainWindow 我可以简单地写这个:

<cust:FileBrowserTextBox  FilePath="{Binding Path=InputFile}" />

【问题讨论】:

    标签: c# wpf xaml user-controls


    【解决方案1】:

    尝试将您的依赖属性设置为UpdateSourceTriggerPropertyChanged

    默认是Default,它返回目标依赖属性的默认UpdateSourceTrigger值。但是,大多数依赖属性的默认值为PropertyChanged,而Text 属性的默认值为LostFocus

    例子:

    <local:FileBrowserTextBox FilePath="{Binding Path=InputFile, 
                                                 Mode=TwoWay,
                                                 UpdateSourceTrigger=PropertyChanged}" />
    

    【讨论】:

    • @Domenico Alessi:如果可行,为什么不接受我的回答? If i use the UpdateSourceTrigger in the UserControl itself it's not working, in the MainWindow yes. - 然而你接受了你没有帮助的答案。
    • 我最后使用了第二个答案,在 UserControl 中添加代码,更简洁,在 MainWindow 中几乎没有输入。我在问题本身中发布了我修复它的方式。我在控件中使用了UpdateSourceTrigger,所以我想接受那个回复。我可以接受你的,但这不是我用过的
    【解决方案2】:

    希望我理解你的问题,

    我已经尝试过相同的方法,并将 UpdateSourceTrigger 设置为 PropertyChanged,同时在 UserControl 的 XAML 代码中绑定 TextBox。下面是我的代码,

     <TextBox Width="200" Name="txtFilepath" Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Path=FilePath, UpdateSourceTrigger=PropertyChanged}"/>
        <Button Width="40" Content=" ... " Click="BrowseButton_Click"/>
    

    而且它正在工作。

    谢谢

    【讨论】:

    • 你为什么要写同样的东西,我已经在我的回答中写过这个?
    • @AnatoliyNikolaev 我已经提到将 UpdateSourceTrigger 添加到 UserControl 本身,而不是在使用时添加它(如您所说)。而且我认为在使用时添加 UpdateSourceTrigger 是行不通的。
    • And I think adding the UpdateSourceTrigger while using it, doesn't work. - 它会工作,我已经测试过了。
    • 如果我在 UserControl 本身中使用 UpdateSourceTrigger 它不起作用,在 MainWindow 中是的。 MainWindow 和 UserControl 中正确的绑定表达式是什么?
    • 好的,我发现这可以进入用户控制&lt;TextBox Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Path=FilePath, UpdateSourceTrigger=PropertyChanged}"/&gt;,而这用于主窗口&lt;cust:FileBrowserTextBox Label="Input File" FilePath="{Binding Path=InputFile, Mode=TwoWay}" /&gt;,有没有办法摆脱TwoWay模式?
    猜你喜欢
    • 2015-09-18
    • 1970-01-01
    • 2016-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-19
    • 1970-01-01
    相关资源
    最近更新 更多