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 绑定无法正常工作 的相关文章

  • 当 AxWindowsMediaPlayer 关闭时,出现 AccessViolation 异常

    我有一个AxWMPLib AxWindowsMediaPlayer在表格上 当我关闭表单时 我收到 尝试读取或写入受保护的内存 这通常表明其他内存已损坏 例外 隐藏表单可以 但关闭则不行 当组件从表单中删除时 一切都很好 这是Winform
  • 滚动 X 轴绘图区域 - Silverlight 柱系列

    我有一个工作正常的柱形系列图表 我有一个需要添加的功能 我希望水平滚动能够启用到 x 轴的绘图区域 这是屏幕截图 如果您看到屏幕截图 我有 6 个项目 并且由于项目数量较多 条形图非常细 所以假设如果我有 20 个项目 那么条形图将根本不可
  • 线程安全的异步字节队列

    我有一个回调方法 只要有新数据可用 就会调用该方法 public delegate void DataCallback byte buffer int offset int count 我想将其包装在一个实现与此类似的接口的类中 publi
  • 重写 WPF 工具包图表中的 DataPointStyle

    我想覆盖DataPointStyle of the LineSeries在我的 WPF 工具包中Chart
  • 使用 INotifyPropertyChanged

    有人可以解释一下为什么在 wpf 中使用绑定时需要使用 INotifyPropertyChanged 的 实现吗 我可以在不实现此接口的情况下绑定属性吗 例如我有代码 public class StudentData INotifyProp
  • 使 DataTemplate 可混合

    如何为 ViewModel 制作可混合的数据模板 可在表达式混合中设计 当我转到资源并尝试直接编辑数据模板时 我在绘图板上看到的只是一个空白矩形 这是因为 DataTemplate 没有绑定到任何东西 当然 我可以创建一个 UserCont
  • 从 xaml 获取 RowIndex

    我有一个带有 DataGridTemplateColumns 的 DataGrid 在 TemplateColumn 中 我使用工作正常的 DataTrigger 它从 DataGrid 父级检索项目计数
  • 在 xaml 中编写嵌套类型时出现设计时错误

    我创建了一个用户控件 它接受枚举类型并将该枚举的值分配给该用户控件中的 ComboBox 控件 很简单 我在数据模板中使用此用户控件 当出现嵌套类型时 问题就来了 我使用这个符号来指定 EnumType x Type myNamespace
  • 先学Silverlight还是先学WPF?

    看来 Silverlight WPF 是 NET 用户界面开发的长期未来 这很棒 因为我可以看到在客户端和 Web 开发端重用 XAML 技能的优势 但看看 WPF XAML Silverlight 它们似乎是非常庞大的技术 那么从哪里开始
  • WPF - 如何从 DataGridRow 获取单元格?

    我有一个具有交替行背景颜色的数据绑定 DataGrid 我想根据单元格包含的数据对单元格进行不同的着色 我已经尝试过该线程建议的解决方案 http wpf codeplex com Thread View aspx ThreadId 511
  • 带动态元素的 WPF 启动屏幕。如何?

    我是 WPF 新手 我需要一些帮助 我有一个加载缓慢的 WPF 应用程序 因此我显示启动屏幕作为权宜之计 但是 我希望能够在每次运行时更改屏幕 并在文本区域中显示不同的引言 这是一个生产力应用程序 所以我将使用非愚蠢但激励性的引言 当然 如
  • 如何在wpf中翻转图像

    我最近学习了如何使用 TransformedBitmap 和 RotateTransformed 类旋转 BitmapImage 现在我可以对图像进行顺时针旋转 但如何翻转图像呢 我找不到执行 BitmapImage 水平和垂直翻转的类 请
  • WPF控件默认大小

    为 wpf 应用程序定义自定义资源主题时 我可以设置宽度 高度等 如何找到这些属性的默认值 即框架中提供的控件中使用的值 WPF 控件通常不包含任何类型的默认大小 WPF 的主要功能点之一是 除非您指定大小 否则所有内容都会动态调整大小 如
  • 从一张图像复制 ROI 并复制到 wpf 中的另一张图像

    我想开发一个具有以下签名的函数 CopyImage ImageSource inputImage Point inTopLeft Point InBottomRight ImageSource outputImage Point outTo
  • 包含内容的 WPF 新窗口

    我想在现有的主 Windwoe 旁边创建一个带有可滚动文本框的新窗口 我在主窗口中按下 打开新窗口 按钮 然后它应该打开一个带有可滚动文本框的新窗口 inside form2 在 WPF 中 您可以在主窗口中拖放元素 但不能在新窗口中执行此
  • 阻止 WPF 文本框增长

    我花了两个小时研究如何避免在输入长文本时我的 WPF TextBox 控件变长 但我无法做到这一点 即使我读过一些关于它的答案 如下所示 停止 wpf textbox from grow with text https stackoverf
  • 更改其他页面的主窗口内容

    在 WPF 应用程序的主窗口中 我有一个 Badged 元素 来自材料设计 这是我的代码
  • WPF根据数据类型设置样式?

    问题就在这里 我将 TreeView 与几种不同类型的对象绑定 每个对象都是一个节点 有些对象有一个名为 IsNodeExpanded 的属性 当然 有些对象则没有 这是我的风格 现在 问题是当绑定不具有此属性的项目时 我们在输出中收到此错
  • 当 AutoGenerateColumns = True 时如何重命名 DataGrid 列?

    我有一个简单的数据结构类 public class Client public String name set get public String claim number set get 我正在将其喂入DataGrid this data
  • 如何将 InputScope 属性添加到 WinRT 中的 PasswordBox?

    如何将输入范围属性添加到我的用户控件的密码框 请你给我解释一下好吗 Thanks 根据我掌握的信息 PasswordBox 在 winrt 中没有输入范围属性 因此您无法直接设置它 如果你想这样做 你必须制作单独的自定义控件 要定义您自己的

随机推荐

  • 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