Since the SL RadEditor doesn't support all the features we need, I'm trying to create a generic wrapper forthe aspnet RadEditor using the HtmlPlaceHolder control. I was hoping to create a silverlght control with some properties like html, image directory, etc that would get passed through to the hosted aspnet RadEditor. I've created the wrapper control but am having problems with my DependencyProperty HtmlProperty. The getters and setters never seem to get called. I added a callback to the dependency property itself and that does work. But this doesn't seem right. Using that "hack", I did get the html from the business object into my HtmlEditor control which was then able to pass it through into the hosted aspx page and the content displayed in the RadEditor. But since my getters/setters don't work, when I click the save button in my parent silverlight control, I can't get notifed to grab the latest html from the hosted RadEditor. Even LostFocus is not firing on HtmlPlaceHolder.
Any ideas on how I can get notified of a save? Shouldn't databanding have queried the "getter" on the htmlproperty?
Any ideas on how I can get notified of a save? Shouldn't databanding have queried the "getter" on the htmlproperty?
public class HtmlEditor : Telerik.Windows.Controls.RadHtmlPlaceholder |
{ |
private bool _isValid = true; |
private string _internalHtml = ""; |
public bool IsValid |
{ |
get { return _isValid; } |
set { _isValid = value; } |
} |
protected string InternalHtml |
{ |
get { return _internalHtml; } |
set { _internalHtml = value; } |
} |
public string Html |
{ |
get |
{ |
//HtmlPlaceHolder placeHolder = obj as HtmlPlaceHolder; |
HtmlElement iframe = (HtmlElement)this.HtmlPresenter.Children[0]; |
// Set an ID to the IFrame so that can be used later when calling the javascript |
iframe.SetAttribute("id", "myIFrame"); |
// Code to be executed |
string code = "document.getElementById('myIFrame').contentWindow.GetEditor().get_Html();"; |
string html=(string) HtmlPage.Window.Eval(code); |
return html; |
//return (string)GetValue(HtmlProperty); |
} |
set |
{ |
SetValue(HtmlProperty, value); |
// |
//value = "<br>hello<br>yeah"; |
////HtmlPlaceHolder placeHolder = obj as HtmlPlaceHolder; |
//HtmlElement iframe = (HtmlElement) this.HtmlPresenter.Children[0]; |
//// Set an ID to the IFrame so that can be used later when calling the javascript |
//iframe.SetAttribute("id", "myIFrame"); |
//// Code to be executed |
//string code = "document.getElementById('myIFrame').contentWindow.GetEditor().set_html('"+value+"');"; |
//HtmlPage.Window.Eval(code); |
} |
} |
public static readonly DependencyProperty HtmlProperty = DependencyProperty.Register("Html", typeof(string), typeof(HtmlEditor),new PropertyMetadata( new PropertyChangedCallback(HtmlChanged)) ); |
//// Accessors for the dependency property: |
public static string GetHtml(DependencyObject obj) |
{ |
return (string)obj.GetValue(HtmlProperty); |
} |
public static void SetHtml(DependencyObject obj, string value) |
{ |
obj.SetValue(HtmlProperty, value); |
} |
public HtmlEditor() |
{ |
this.Loaded += new RoutedEventHandler(HtmlEditor_Loaded); |
this.GotFocus += new RoutedEventHandler(TextBox_GotFocus); |
this.LostFocus += new RoutedEventHandler(TextBox_LostFocus); |
this.BindingValidationError += new EventHandler<ValidationErrorEventArgs>(TextBox_BindingValidationError); |
HtmlPage.RegisterScriptableObject("HtmlEditor", this); |
} |
void HtmlEditor_Loaded(object sender, RoutedEventArgs e) |
{ |
string url = " url to generic editor page "; |
this.SourceUrl = new Uri(url); |
BindingExpression be=this.GetBindingExpression(HtmlProperty); |
} |
private static void HtmlChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) |
{ |
// this gets called. But why none of the setters above? |
((HtmlEditor)sender).InternalHtml = (string) e.NewValue; |
} |
void TextBox_GotFocus(object sender, RoutedEventArgs e) |
{ |
} |
void TextBox_LostFocus(object sender, RoutedEventArgs e) |
{ |
// grab latest html from hosted control |
//HtmlPlaceHolder placeHolder = obj as HtmlPlaceHolder; |
HtmlElement iframe = (HtmlElement)this.HtmlPresenter.Children[0]; |
// Set an ID to the IFrame so that can be used later when calling the javascript |
iframe.SetAttribute("id", "myIFrame"); |
// try 1 |
string code = "document.getElementById('myIFrame').contentWindow.GetEditor().get_html();"; |
_internalHtml = (string)HtmlPage.Window.Eval(code); |
// try 2 |
//string code = "document.getElementById('myIFrame').contentWindow.SaveHtml();"; |
//HtmlPage.Window.Eval(code); |
} |
void TextBox_BindingValidationError(object sender, ValidationErrorEventArgs e) |
{ |
if (e.Action == ValidationErrorEventAction.Added) |
_isValid = false; |
else |
IsValid = true; |
} |
public event EventHandler ValueChanged; |
private void OnValueChanged() |
{ |
if (ValueChanged != null) ValueChanged(this, EventArgs.Empty); |
} |
// called by hosted page onload to get html to insert into editor |
[ScriptableMember] |
public string GetHtml() |
{ |
return this.InternalHtml; |
} |
[ScriptableMember] |
public void SaveHtml(string html) |
{ |
this.InternalHtml = html; |
} |
} |