Silverlight dependency property snafu,我做错了什么?
我正在增强一个开源控件,以添加一些我需要的功能,我陷入了以下问题中,令人绝望: 控件是一个富文本框,支持HTML,但不通过属性;你必须这样做:Silverlight dependency property snafu,我做错了什么?,silverlight,properties,Silverlight,Properties,我正在增强一个开源控件,以添加一些我需要的功能,我陷入了以下问题中,令人绝望: 控件是一个富文本框,支持HTML,但不通过属性;你必须这样做: var sHtml = "..." ctrl.LoadHtml(sHtml) 及 到目前为止还不错。但是我想通过数据绑定设置HTML,所以我创建了一个称为HTML的依赖属性: public static readonly DependencyProperty HtmlProperty = DependencyProperty.R
var sHtml = "..."
ctrl.LoadHtml(sHtml)
及
到目前为止还不错。但是我想通过数据绑定设置HTML,所以我创建了一个称为HTML的依赖属性:
public static readonly DependencyProperty HtmlProperty =
DependencyProperty.Register(
"Html",
typeof(string),
typeof(RichTextEditor),
new PropertyMetadata(string.Empty, new PropertyChangedCallback(HtmlChangedCallback))
);
public string Html
{
get {return (string)GetValue(HtmlProperty);}
set {SetValue(HtmlProperty, value);}
}
private static void HtmlChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
//get the control
var rte = (RichTextEditor)d;
//got here, so load the html
rte.TextBox.LoadHtml((string)e.NewValue);
}
这一切都很好。我遇到的问题是,当控件的内容发生更改时,我不知道如何通知属性系统。控件具有ContentChanged事件,因此我尝试了以下方法:
private void rtb_ContentChanged(object sender, RichTextBoxEventArgs e)
{
//tell the html prop that it changed
SetValue(HtmlProperty, rtb.SaveHtml());
}
但这会触发HtmlChangedCallback,重新进入会导致问题。然后我试着用了一个重新进入的标志,但那很混乱,因为事件的顺序比我预期的要复杂,在这一点上我想我肯定遗漏了什么,所以我在这里问。请帮忙!提前谢谢
顺便说一句,该控件不支持INotifyPropertyChanged,实现它超出了范围,因为该控件很大,我不想做那么多工作。为什么需要通知属性系统?您正在尝试更新数据绑定的源吗?控件不必实现INotifyPropertyChanges;该接口必须在为数据绑定提供数据的类上实现 如果现在忽略保存/加载HTML,而只是将HTML存储为字符串,会怎么样?它能正常工作吗 这是一个对我来说很好的例子
class MyControl
{
public int Value
{
get
{
return (int)GetValue(ValueProperty);
}
set
{
SetValue(ValueProperty, value);
Count.Text = value.ToString();
}
}
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value",
typeof(int),
typeof(Vote),
new PropertyMetadata(0, OnValueChanged));
private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((MyControl)d).Value = (int)e.NewValue;
}
计数是一个文本块控件。为什么需要通知属性系统?您正在尝试更新数据绑定的源吗?控件不必实现INotifyPropertyChanges;该接口必须在为数据绑定提供数据的类上实现 如果现在忽略保存/加载HTML,而只是将HTML存储为字符串,会怎么样?它能正常工作吗 这是一个对我来说很好的例子
class MyControl
{
public int Value
{
get
{
return (int)GetValue(ValueProperty);
}
set
{
SetValue(ValueProperty, value);
Count.Text = value.ToString();
}
}
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value",
typeof(int),
typeof(Vote),
new PropertyMetadata(0, OnValueChanged));
private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((MyControl)d).Value = (int)e.NewValue;
}
计数是一个文本块控件。这是一个典型的小问题,通常用一个简单的布尔标志来解决
private bool suppressHtmlChanged = false;
private static void HtmlChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var rte = (RichTextEditor)d;
if (!rte.suppressHtmlChanged)
rte.TextBox.LoadHtml((string)e.NewValue);
}
private void rtb_ContentChanged(object sender, RichTextBoxEventArgs e)
{
suppressHtmlChanged = true;
SetValue(HtmlProperty, rtb.SaveHtml());
suppressHtmlChanged = false;
}
如今,这样的解决方案似乎太过时了,不是吗?我们常常可以说服自己,这样的“低技术”解决方案不可能是正确的,因为它们不“优雅” 这是一个典型的小问题,通常用一个简单的布尔标志来解决
private bool suppressHtmlChanged = false;
private static void HtmlChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var rte = (RichTextEditor)d;
if (!rte.suppressHtmlChanged)
rte.TextBox.LoadHtml((string)e.NewValue);
}
private void rtb_ContentChanged(object sender, RichTextBoxEventArgs e)
{
suppressHtmlChanged = true;
SetValue(HtmlProperty, rtb.SaveHtml());
suppressHtmlChanged = false;
}
如今,这样的解决方案似乎太过时了,不是吗?我们常常可以说服自己,这样的“低技术”解决方案不可能是正确的,因为它们不“优雅” “重新进入”导致了什么问题?最初的问题是,在HtmlChangedCallback中,我将html加载到控件中,该控件触发Content_Changed事件,在Content_Changed中调用SetValue导致HtmlChangedCallback触发,在Silverlight逃离无限循环之前,我已经看到了很多次。我试着自己设置一个重新进入的标志,但我发现事件的顺序是不可预测的,有时事件会不按顺序发生,而不是试图去弄清楚,如果我不得不这么做,我可以看出我做错了什么。“重新进入”导致了什么问题?嗯,最初的问题是,在HtmlChangedCallback中,我将html加载到控件中,该控件触发Content_Changed事件,在Content_Changed中调用SetValue导致HtmlChangedCallback触发,在Silverlight逃脱无限循环之前,我已经看到了很多次这样的情况。我试着自己设置一个重新进入标志,但我发现事件的顺序是不可预测的,有时它们会出现顺序错误,而不是试图找出它,如果我不得不这么做,我可以判断我做错了什么。是的,我有一个视图模型,应该在视图中的Html出现时更新(即rich textbox)更改。不,仅存储字符串不起作用,因为属性系统仍然无法知道视图更改了字符串。我的问题是:当发生这种情况时,告诉它的正确方法是什么?是否在{Binding}中指定了双向模式语句?为了使事情正常工作,您需要三件事-模型应该实现INotifyPropertyChanges并调用属性更改事件-视图应该使用dependency属性(使用Get/SetValue存储)-XAML应该指定双向模式我认为这三个步骤还不够,因为我已经完成了所有步骤。进一步考虑后,我认为缺少的部分非常普遍:当您指定从视图更新源的绑定时(例如双向),而视图没有实现INPC,它将如何工作?也就是说,视图必须有一种方法来通知属性已更改,我认为应该可以通过DependencyProperty实现,但我不太确定,因为我找不到。因此,如果我希望视图支持更新源代码,那么视图可能必须实现INPC。View知道更新绑定,因为视图使用SetValue存储属性。SetValue将执行所有必要的更新。我在控件中执行的另一项操作。我总是从通知回调调用rte.Htlm=e.NewValue。当您说这些操作不起作用时,您的意思是什么?您在co上获得modelview集的初始值吗控件?我得到的通知回调很好。但是用户在文本框中键入,现在html已经更改。控件应该如何通知属性系统发生了这种情况?调用SetValue(HtmlProperty,html)不起作用,因为它会触发通知回调。是的,我有一个ViewModel,当视图中的Html(即富文本框)出现时应该更新它更改。不,仅存储字符串不起作用,因为属性系统仍然无法知道视图已更改了字符串。我的问题是:当更改字符串时,正确的方法是什么