CustomControl DependencyProperty 绑定无法正常工作

2023-12-11

我写了一个自定义控件。它是一个带有按钮的文本框,可打开 OpenFileDialog。

TextBox 的 Text 属性绑定到我的依赖属性“FileName”。如果用户通过 OpenFileDialog 选择文件,我会将结果设置为此属性。

TextBox 通过绑定获取正确的值。

但现在我的问题。就我而言,我使用的是 ViewModel。因此,我将 DependencyProperty“FileName” 绑定到 ViewModel 中的属性。 更改“FileName”属性(直接更改到文本框或通过对话框选择文件)后,viewmodel 属性不会更新。

自定义控件.xaml.cs

using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Win32;

namespace WpfApplication1.CustomControl
{
    /// <summary>
    /// Interaction logic for FileSelectorTextBox.xaml
    /// </summary>
    public partial class FileSelectorTextBox
        : UserControl, INotifyPropertyChanged
    {
        public FileSelectorTextBox()
        {
            InitializeComponent();

            DataContext = this;
        }

        #region FileName dependency property

        public static readonly DependencyProperty FileNameProperty = DependencyProperty.Register(
            "FileName",
            typeof(string),
            typeof(FileSelectorTextBox),
            new FrameworkPropertyMetadata(string.Empty,
                FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                new PropertyChangedCallback(OnFileNamePropertyChanged),
                new CoerceValueCallback(OnCoerceFileNameProperty)));

        public string FileName
        {
            get { return (string)GetValue(FileNameProperty); }
            set { /*SetValue(FileNameProperty, value);*/ CoerceFileName(value); }
        }

        private bool _shouldCoerceFileName;
        private string _coercedFileName;

        private object _lastBaseValueFromCoercionCallback;
        private object _lastOldValueFromPropertyChangedCallback;
        private object _lastNewValueFromPropertyChangedCallback;
        private object _fileNameLocalValue;
        private ValueSource _fileNameValueSource;

        private static void OnFileNamePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is FileSelectorTextBox)
            {
                (d as FileSelectorTextBox).OnFileNamePropertyChanged(e);
            }
        }

        private void OnFileNamePropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            LastNewValueFromPropertyChangedCallback = e.NewValue;
            LastOldValueFromPropertyChangedCallback = e.OldValue;

            FileNameValueSource = DependencyPropertyHelper.GetValueSource(this, FileNameProperty);
            FileNameLocalValue = this.ReadLocalValue(FileNameProperty);
        }

        private static object OnCoerceFileNameProperty(DependencyObject d, object baseValue)
        {
            if (d is FileSelectorTextBox)
            {
                return (d as FileSelectorTextBox).OnCoerceFileNameProperty(baseValue);
            }
            else
            {
                return baseValue;
            }
        }

        private object OnCoerceFileNameProperty(object baseValue)
        {
            LastBaseValueFromCoercionCallback = baseValue;

            return _shouldCoerceFileName ? _coercedFileName : baseValue;
        }

        internal void CoerceFileName(string fileName)
        {
            _shouldCoerceFileName = true;
            _coercedFileName = fileName;
            CoerceValue(FileNameProperty);
            _shouldCoerceFileName = false;
        }

        #endregion FileName dependency property

        #region Public Properties

        public ValueSource FileNameValueSource
        {
            get { return _fileNameValueSource; }
            private set
            {
                _fileNameValueSource = value;
                OnPropertyChanged("FileNameValueSource");
            }
        }

        public object FileNameLocalValue
        {
            get { return _fileNameLocalValue; }
            set
            {
                _fileNameLocalValue = value;
                OnPropertyChanged("FileNameLocalValue");
            }
        }

        public object LastBaseValueFromCoercionCallback
        {
            get { return _lastBaseValueFromCoercionCallback; }
            set
            {
                _lastBaseValueFromCoercionCallback = value;
                OnPropertyChanged("LastBaseValueFromCoercionCallback");
            }
        }

        public object LastNewValueFromPropertyChangedCallback
        {
            get { return _lastNewValueFromPropertyChangedCallback; }
            set
            {
                _lastNewValueFromPropertyChangedCallback = value;
                OnPropertyChanged("LastNewValueFromPropertyChangedCallback");
            }
        }

        public object LastOldValueFromPropertyChangedCallback
        {
            get { return _lastOldValueFromPropertyChangedCallback; }
            set
            {
                _lastOldValueFromPropertyChangedCallback = value;
                OnPropertyChanged("LastOldValueFromPropertyChangedCallback");
            }
        }

        #endregion FileName dependency property

        private void btnBrowse_Click(object sender, RoutedEventArgs e)
        {
            FileDialog dlg = null;

            dlg = new OpenFileDialog();

            bool? result = dlg.ShowDialog();

            if (result == true)
            {
                FileName = dlg.FileName;
            }

            txtFileName.Focus();
        }

        #region INotifyPropertyChanged

        public event PropertyChangedEventHandler PropertyChanged;

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

        #endregion INotifyPropertyChanged
    }
}

自定义控件.xaml

<UserControl x:Class="WpfApplication1.CustomControl.FileSelectorTextBox"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             mc:Ignorable="d"
             d:DesignHeight="23" d:DesignWidth="300">
    <Border BorderBrush="#FF919191"
            BorderThickness="0">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*" MinWidth="80" />
                <ColumnDefinition Width="30" />
            </Grid.ColumnDefinitions>

            <TextBox Name="txtFileName"
                     HorizontalAlignment="Stretch"
                     VerticalAlignment="Center"
                     Grid.Column="0"
                     Text="{Binding FileName}" />

            <Button Name="btnBrowse"
                    Click="btnBrowse_Click"
                    HorizontalContentAlignment="Center"
                    ToolTip="Datei auswählen"
                    Margin="1,0,0,0"
                    Width="29"
                    Padding="1"
                    Grid.Column="1">
                <Image Source="../Resources/viewmag.png"
                       Width="15"
                       Height="15" />
            </Button>
        </Grid>
    </Border>
</UserControl>

在视图中使用:

<Window x:Class="WpfApplication1.MainView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:vm="clr-namespace:WpfApplication1.ViewModels"
        xmlns:controls="clr-namespace:WpfApplication1.CustomControl"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <vm:MainViewModel />
    </Window.DataContext>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="10" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <DataGrid ItemsSource="{Binding Files}" AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTemplateColumn Header="File name" Width="*">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <controls:FileSelectorTextBox FileName="{Binding .}" Height="30" />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>

        <ListBox ItemsSource="{Binding Files}" Grid.Row="2">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding}" />
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
</Window>

和视图模型:

using System.Collections.ObjectModel;
using System.ComponentModel;

namespace WpfApplication1.ViewModels
{
    internal class MainViewModel
        : INotifyPropertyChanged
    {
        public MainViewModel()
        {
            Files = new ObservableCollection<string> { "test1.txt", "test2.txt", "test3.txt", "test4.txt" };
        }

        #region Properties

        private ObservableCollection<string> _files;

        public ObservableCollection<string> Files
        {
            get { return _files; }
            set
            {
                _files = value;
                OnPropertyChanged("Files");
            }
        }

        #endregion Properties

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

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

        #endregion INotifyPropertyChanged Members
    }
}

依赖属性的使用是否有错误? 注意:该问题仅发生在 DataGrid 中。


需要设置绑定Mode to TwoWay,因为默认情况下绑定以一种方式工作,即从视图模型加载更改,但不将其更新回来。

<controls:FileSelectorTextBox FileName="{Binding FileName, Mode=TwoWay}" Height="30" />

另一种选择是声明您的自定义依赖属性BindsTwoWayByDefault标志,像这样:

public static readonly DependencyProperty FileNameProperty =
            DependencyProperty.Register("FileName", 
                                        typeof(string), 
                                        typeof(FileSelectorTextBox), 
                                        new FrameworkPropertyMetadata(default(string), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

此外,当您从控件内部更改自定义依赖属性时,请使用SetCurrentValue方法而不是使用属性设置器直接分配值。因为如果直接分配它,就会破坏绑定。

所以,而不是:

FileName = dlg.FileName;

这样做:

SetCurrentValue(FileNameProperty, dlg.FileName);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

CustomControl DependencyProperty 绑定无法正常工作 的相关文章

  • C# 线程安全(特别是 MVVM/WPF)

    我想知道我需要做什么才能使模型在 MVVM 中线程安全 假设我有以下类 它被实例化为单例 public class RunningTotal INotifyPropertyChange private int total public in
  • DispatcherTimer Stop 不停止

    更新 我把完整的代码放出来供参考 我正在尝试使用 Dispatcher 方法而不是 Forms Timer 我在方法结束时停止了 但在停止之前它一直循环多次 什么地方出了错 顺便说一句 我必须提到我确实在计时器 if 语句中使用了 Mess
  • 如何制作自定义组件属性?

    我需要帮助来制作一个控件属性 当您单击它时 它会弹出一个自定义对话框 例如设置 就像 TPicture 一样 有什么想法或建议吗 如果您的类用作其他组件的属性 并且您想使用对象检查器来调用对话框 那么您必须实现并注册一个自定义属性编辑器 例
  • 如何动态更改 WPF 中 DataGridTextColumn 绑定上的转换器?

    我真的不明白 WPF 和 XAML 并且继承了一些写得很糟糕的代码 所以我可能会扼杀它 但这里是 我继承了一个绑定到 Person 对象列表 在代码后面 的 DataGrid 其中必要的 DataGridTextColumn 在 XAML
  • 是否有其他方法可以在 C# 中使用 WPF 处理 DICOM 图像而无需任何第三方/库?

    我开始从事一个充满挑战的新项目 我正在从事一个医疗项目 我必须读取 DICOM 图像并利用其属性处理图像 我收集了一些关于 DICOM 和 PACS 的基本知识 由于我在 WPF 上工作了大约 2 年的职业生涯 因此我选择使用 C 和 WP
  • wpf中基于绑定bool属性的样式对象

    如何使用 wpf 中的 xaml 更改我在 mvvm 设置中要使用的对象的填充颜色 当绑定的属性设置为 True 时 我想将填充颜色更改为红色 该属性称为 IsRound 如果需要的话我会发布代码 我现在不在电脑上 UPDATED 有人可以
  • 如何将启动时窗口的位置定位到用户屏幕的右侧?

    我目前正在用 C 创建一个类似侧边栏的 WPF 应用程序 当用户启动应用程序时 我希望窗口自动将其自身定位到用户屏幕的一侧 我尝试了一些方法和谷歌搜索 但没有找到任何帮助 这是我正在尝试做的事情的一个例子 http prntscr com
  • WPF 数据绑定到字符串属性

    我有一个关于数据绑定的问题 我正在努力解决这个问题 我的 xaml cs 文件中有以下属性 private string stationIdInstruction public event PropertyChangedEventHandl
  • WPF 通过宽高比调整 UserControl 的大小

    我有一个 UserControl 并且该 UserControl 必须根据宽高比调整大小 这意味着 宽度 高度 2 1 目前我正在使用这段代码 protected override Size ArrangeOverride Size arr
  • 列表框仅显示一项

    我有一个ListBox和一个带有字符串的类 每次用户单击应用程序中的添加按钮时 我都会创建该类的一个新实例并将其添加到绑定到的列表中ListBox 第一次单击 添加 按钮时 列表框显示第一项 但下次单击时不再显示两项 XAML 这是List
  • WPF RichTextBox 中的只读 Run 元素?

    我可能完全是在想象这一点 但我可以发誓有一种方法可以使 RichTextBox 中的各个 Run 或 Parapgraph 元素成为只读 我还可以发誓 几周前我自己尝试了一种方法 并对结果感到满意 我隐约记得它看起来像这样
  • 使用 C# 从 UIElement 截取 WPF 屏幕截图 JPG

    我正在尝试从我的 WPF 应用程序的一部分创建 JPG 就像截图一样 只是个人的UIElements 我从这里开始 http www grumpydev com 2009 01 03 take wpf screenshots http ww
  • CanExecute 何时被调用?

    在演示中 我有一个按钮可以切换布尔字段isAsking 我创建了一个命令 该命令仅在以下情况下执行isAsking true 一旦我按下切换按钮 okButton IsEnable立即更改 这表明该命令发现了更改isAsking 我感到很困
  • DockPanel 选项卡顺序

    我在 ItemsControl 的 DataTemplate 中设置了一个 DockPanel 如下所示
  • 良好的 WPF 或 silverlight windows 小工具示例

    有人有 WPF 或 silverlight windows 小工具的好例子吗 诺兰多02 您好 我在网上看到了一些侧边栏小工具演示和教程 我将在这里列出它们以供您审查 希望其中一些能引起您的注意 并为您的努力提供帮助 WPF http ww
  • 文本框的自定义日期格式

    有关的 将3个文本框绑定在一起 相同的日期时间不同的格式 https stackoverflow com questions 35581427 binding 3 textboxes together same datetime diffe
  • WCF 中是否可以在没有无参数构造函数的情况下序列化对象?

    我知道私有无参数构造函数可以工作 但是没有无参数构造函数的对象又如何呢 我想公开来自第三方库的类型 因此我无法控制类型定义 如果有办法的话什么是最简单的 例如 我不知道必须创建子类型 Edit 我正在寻找类似此处所示的定制级别 http m
  • 获取上下文菜单的控制

    我有一个如下所示的上下文菜单 A 1 2 3 选择 1 2 或 3 后 我需要访问调用上下文菜单的对象 意思是如果这是 textbox1 的上下文菜单 那么我需要访问该对象 我该怎么做 忘了说了 这是一个WPF应用程序 所以我使用 Syst
  • 绑定到后面代码中的相对源

    在我的 UserControl 中 我的 XAML 中有以下代码
  • 如何在选项卡控件对象中禁用选项卡换行

    我正在 WPF C 中设计 GUI 并且使用Tab Control目的 我的tab control将包含很多选项卡 我想知道如何禁用对象的默认 包装 行为 基本上相反this https stackoverflow com question

随机推荐

  • DataGrid - “双向绑定需要 Path 或 XPath。”

    我想在 DataGrid 上显示我的对象数据库 public class Student public string Imie get set public string Nazwisko get set string Numer get
  • 边框 CSS HTML 中的文本

    我想要一个看起来像这样的 div 这可以用 HTML CSS 实现吗 我还将使用 jQuery 为这个 div 制作动画 当 div 隐藏时 我希望显示标题和顶行 是的 但这不是一个div 它是fieldset fieldset borde
  • Android Studio - 构建错误 - Android 任务已创建

    构建项目时出现如下错误 错误 2 0 Android 任务已创建 调用 android applicationVariants 时会发生这种情况 android libraryVariants 或 android testVariants
  • NSLocalizedString()的第二个参数是什么?

    是什么 comment参数在 NSString NSLocalizedString NSString key NSString comment 如果我这样做 NSLocalizedString Hello World Key Hello W
  • 如何防止 Spyne 包装我的回复?

    这是示例服务 NS my app namespace class MyMethodRS ComplexModel tns NS Version XmlAttribute Unicode class MyService ServiceBase
  • Django Haystack 和 Whoosh 搜索工作正常,但 SearchQuerySet 返回 0 个结果

    编辑 更多信息在帖子底部 原问题 我似乎遇到了与这个 未解决的 问题相同的问题 django haystack Whoosh SearchQuerySet all 始终无 我已经在我的 Django 项目上使用 Whoosh 设置了 Hay
  • 使用ffmpeg丢弃容器中的数据流

    我正在尝试使用 ffmpeg 删除 Mp4 容器内的数据 字幕 流 这是 ffprobe 的屏幕截图 Input 0 mov mp4 m4a 3gp 3g2 mj2 from test m4v Metadata major brand is
  • Ansible,如何在主机清单中定义列表?

    我有一个剧本 我想在我的主机文件中定义一个字符串列表 这是我的主机文件 dashboard 1 2 3 4 dashboard domain test site domain one two foo bar 这是我尝试使用以下方法编写的剧本
  • WCF 中的 Owin 中间件替代品是什么?

    我正在尝试在 WCF 应用程序中实现多租户 但面临一些问题 所以我已经在应用程序中配置了 Autofac 并且 Autofac 也支持多租户与WCF 现在我的情况略有不同 我有一个正在使用此 WCF 服务的移动应用程序 该服务部署在 Azu
  • Microsoft Office 365 组:来宾用户无法使用图形端点进行驱动器调用[关闭]

    Closed 这个问题是无法重现或由拼写错误引起 目前不接受答案 我们的应用程序通过对驱动器项执行 Get 调用来读取组驱动器内容 这对于内部成员和来宾用户来说过去都工作得很好 它现在适用于内部成员 但不再适用于来宾用户 以下是示例调用 h
  • 网页抓取协助

    我必须从这个网页中提取一些信息 我知道有更简单的方法来获取这些信息 但这就是我的任务 到目前为止 我一直在尝试这样做 import pandas as pd import requests from bs4 import Beautiful
  • 为什么这两个正则表达式的行为不一样?

    我正在尝试使用这样的构造函数语法创建正则表达式new RegExp bword b g 但它的行为并不符合预期 相反 它似乎创建了一个如下所示的正则表达式 bwor b g缺少最后一个字母 我必须使用构造函数语法来创建正则表达式 因为我是从
  • R data.table 如果另一列为 NA,则删除一列重复的行

    这是一个示例 data table dt lt data table col1 c A A B C C D col2 c NA dog cat jeep porsch NA col1 col2 1 A NA 2 A dog 3 B cat
  • Linq To Sql - SQL 默认约束问题

    我在数据库中有一个 USER 表 该表有一个 RegistrationDate 列 该列的默认约束为 GETDATE 使用 LINQ 时 我不为 RegistrationDate 列提供任何数据以将其设置为默认值 但 SQL Server
  • 并非所有代码路径都会返回值,for 循环

    这段代码将比较用户名 and 密码存储在文本文件中 我认为这是因为 for 循环 它可能很简单 但我看不到它 public int loginCheck string users File ReadLines Username Passwo
  • 如何将 Crashlytics 与 iMessage 扩展一起使用?

    我的 iOS 应用程序中有一个 iMessage 扩展 Crashlytics 能否捕获其崩溃情况 我尝试添加相同的Fabric来自我的主应用程序的条目Info plist进入我的 iMessage 扩展程序Info plist 并将以下内
  • Libsvm 中的决策值

    我是 SVM 新手 我使用 Libsvm for Matlab 在预测阶段之后我得到了一个决策值数组 根据 SVM 理论 每个测试记录 z 被指定为正 如果 f z 1 其中 f z 定义为 f z 符号 w z b 那么如何将实例 z 的
  • 在 JBoss 中替换 Websphere 的 WorkManager?

    我们正在从 Websphere 迁移到 JBoss 但某些代码依赖于 Websphere 的 WorkManager com ibm websphere asyncbeans WorkManager 有没有人以前处理过这个问题 并对如何替换
  • 具有两个 Y 轴的图:置信区间

    我试图用误差线和两个 y 轴绘制几个点 然而 在每次调用plotCI 或errbar 函数时 都会初始化一个新的绘图 无论是否有par new TRUE 调用 require plotrix x lt 1 10 y1 lt x rnorm
  • CustomControl DependencyProperty 绑定无法正常工作

    我写了一个自定义控件 它是一个带有按钮的文本框 可打开 OpenFileDialog TextBox 的 Text 属性绑定到我的依赖属性 FileName 如果用户通过 OpenFileDialog 选择文件 我会将结果设置为此属性 Te