有以下几种方式可以考虑:
1、在代码执行过程中动态改变windowless 属性。最初的想法是党textbox获取焦点的时候,让windowless =flase,失去焦点的时候在还原回去 。很不幸,windowless 无法动态更改(只读属性)。
2、用一个html的input元素来充当输入设备,漂浮在一个假的输入框上。经过我的尝试,效果很不错。足以以假乱真。
缺点是必须在宿主html页面上加两个css样式。我也不知道为什么sl动态生成的有些样式不起作用,只能从从html页面加载才可以。
按照第二条想法,我封装了一个输入控件,在自己的项目中用,感觉还是可以解决问题。当然还是希望微软在日后把这个不支持输入中文的Bug修复。
为了支持windowless=false,在程序中判断该属性,来决定是用内置的textbox作为输入设备还是使用input作为输入设备。
截了两张图:
输入的时候:
显示的时候:
实现代码如下:
cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Browser;
namespace Sl.Input
{
/// <summary>
/// 使用的时候请在sl宿主页面加入样式
/// .inputcss
/// {
/// border-collapse: collapse;
/// border: solid 0px Transparent; background-color: Transparent;
/// }
/// .divInputcss
/// {
/// border: solid 0px Transparent; background-color:Transparent;
/// position: absolute; display: none; z-index:1000;
/// }
/// </summary>
public partial class SLInput : UserControl
{
HtmlElement divIndicatorName;
HtmlElement txtIndicatorNameElements;
public delegate void KeyDownHandel(object sender, string keyCode);
public event KeyDownHandel KeyDownHandelEvent;
public SLInput()
{
InitializeComponent();
System.Windows.Interop.SilverlightHost host = Application.Current.Host;
System.Windows.Interop.Settings setting = host.Settings;
bool isWindowless = setting.Windowless;
if (isWindowless == true)
{
CreateHtmlElement();
this.SizeChanged += new SizeChangedEventHandler(EsmsInput_SizeChanged);
this.txtBox.Visibility = Visibility.Collapsed;
this.txtIndicatorName.Visibility = Visibility.Visible;
}
}
/// <summary>
/// 当这个控件大小发生了变化,需要重新调整input的大小
/// </summary>
void EsmsInput_SizeChanged(object sender, SizeChangedEventArgs e)
{
divIndicatorName.SetStyleAttribute("width", e.NewSize.Width.ToString() + "px");
divIndicatorName.SetStyleAttribute("heght", e.NewSize.Height.ToString() + "px");
txtIndicatorNameElements.SetStyleAttribute("width", e.NewSize.Width.ToString() + "px");
txtIndicatorNameElements.SetStyleAttribute("heght", e.NewSize.Height.ToString() + "px");
}
/// <summary>
/// 创建一个input 元素作为输入设备
/// </summary>
void CreateHtmlElement()
{
divIndicatorName = HtmlPage.Document.CreateElement("div");
txtIndicatorNameElements = HtmlPage.Document.CreateElement("input");
divIndicatorName.AppendChild(txtIndicatorNameElements);
divIndicatorName.SetStyleAttribute("display", "none");
divIndicatorName.SetStyleAttribute("position", "absolute");
divIndicatorName.SetStyleAttribute("z-index", "10000");
divIndicatorName.SetStyleAttribute("left", string.Format("{0}px", 0));
divIndicatorName.SetStyleAttribute("top", string.Format("{0}px", 0));
//这个样式必须放在html中,动态生成的样式不起作用,原因不明
divIndicatorName.CssClass = "divInputcss";
txtIndicatorNameElements.SetStyleAttribute("background-color", "Transparent");
//这个样式必须放在html中,动态生成的样式不起作用,原因不明
txtIndicatorNameElements.CssClass = "inputcss";
HtmlPage.Document.Body.AppendChild(divIndicatorName);
txtIndicatorNameElements.AttachEvent("onblur", new EventHandler(onLostFocus));
//注册一个keydown事件用于托管代码中调用
txtIndicatorNameElements.AttachEvent("onkeydown", new EventHandler(onExecuteQueryByonKeyDown));
//这是一个用border画的虚假的输入框,当它被点击的时候,显示input元素,并定位到这个border上面
this.bdInputName.MouseLeftButtonDown += new MouseButtonEventHandler(bdInputName_MouseLeftButtonDown);
}
private void onLostFocus(object sender, EventArgs e)
{
hideHtmlElementByResize(null, null);
}
private void onExecuteQueryByonKeyDown(object sender, EventArgs e)
{
if (KeyDownHandelEvent != null)
{
string keyCode = HtmlPage.Window.Eval("event.keyCode").ToString();
KeyDownHandelEvent(this, keyCode);
}
}
private void hideHtmlElementByResize(object sender, EventArgs e)
{
divIndicatorName.SetStyleAttribute("display", "none");
divIndicatorName.SetStyleAttribute("left", string.Format("{0}px", 0));
divIndicatorName.SetStyleAttribute("top", string.Format("{0}px", 0));
this.txtIndicatorName.Text = txtIndicatorNameElements.GetAttribute("value");
this.txtIndicatorName.Opacity = 1;
Application.Current.Host.Content.Resized -= new EventHandler(hideHtmlElementByResize);
}
void bdInputName_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Point posRoot = e.GetPosition(null);
Point posRela = e.GetPosition(this.bdInputName);
double left = posRoot.X - posRela.X + 2;
double top = posRoot.Y - posRela.Y + 2;
divIndicatorName.SetStyleAttribute("display", "block");
divIndicatorName.SetStyleAttribute("left", string.Format("{0}px", left));
divIndicatorName.SetStyleAttribute("top", string.Format("{0}px", top));
divIndicatorName.SetStyleAttribute("position", "absolute");
txtIndicatorNameElements.SetAttribute("value", this.txtIndicatorName.Text);
txtIndicatorNameElements.Focus();
this.txtIndicatorName.Opacity = 0;
Application.Current.Host.Content.Resized += new EventHandler(hideHtmlElementByResize);
}
public double EsmsWidth
{
set
{
this.bdInputName.Width = value;
EsmsInputWidth = value;
}
get
{
return this.bdInputName.Width;
}
}
public double EsmsHeight
{
set
{
this.bdInputName.Height = value;
EsmsInputHeight = value;
}
get
{
return this.bdInputName.Height;
}
}
public double EsmsInputWidth
{
set
{
if (this.txtIndicatorNameElements != null)
{
this.txtIndicatorNameElements.SetStyleAttribute("width", (value - 4).ToString());
this.divIndicatorName.SetStyleAttribute("width", (value - 4).ToString());
this.txtIndicatorName.Width = value;
}
}
get
{
return this.bdInputName.Width;
}
}
public double EsmsInputHeight
{
set
{
if (this.txtIndicatorNameElements != null)
{
this.txtIndicatorNameElements.SetStyleAttribute("height", (value - 4).ToString());
this.divIndicatorName.SetStyleAttribute("height", (value - 4).ToString());
}
}
get
{
return this.bdInputName.Height;
}
}
public string Text
{
get
{
if (txtIndicatorNameElements != null)
{
this.txtIndicatorName.Text = txtIndicatorNameElements.GetAttribute("value");
}
return this.txtIndicatorName.Text;
}
set
{
this.txtIndicatorName.Text = value;
if (txtIndicatorNameElements != null)
{
txtIndicatorNameElements.SetAttribute("value", value ?? "");
}
}
}
}
}
xaml:
<UserControl x:Class="Sl.Input.SLInput"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid x:Name="LayoutRoot">
<Border MinWidth="50" MinHeight="22" Grid.Column="1" BorderThickness="1,1,1,1" CornerRadius="2,2,2,2" x:Name="bdInputName" ToolTipService.ToolTip="模糊查询" BorderBrush="#FF005D93">
<Border.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFEFFAFE"/>
<GradientStop Color="#FFD6F0FA" Offset="1"/>
</LinearGradientBrush>
</Border.Background>
<Grid>
<TextBox x:Name="txtBox" Visibility="Visible"></TextBox>
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" Height="Auto" Margin="2" x:Name="txtIndicatorName" Text="" Width="Auto" TextWrapping="NoWrap" FontFamily="MS Reference Sans Serif" Visibility="Collapsed">
</TextBlock>
</Grid>
</Border>
</Grid>
</UserControl>