SilverLight之路(四)

接上回,现在我们来实现风险测试模块的测试题界面,这里主要是ItemsControl控件与ListBox控件的使用以及WCF的应用。

如图

 SilverLight之路(四)

类似这样的内容,应该不会想手动去添加每一项吧,没错,应该是数据库查询,然后绑定才对,在web中,我们可以两个repeater搞定,那么在sl里呢?应该也有类似的办法吧,不过找来找去,没有发现所谓的repeater或者datalist,只是找到了一个ItemsControl,那么这个是不是我们想要的东西呢?管它呢,先拿出来看看。

新建一个测量题页面,结构如下

 SilverLight之路(四) 

 SilverLight之路(四)

页面有了,我们再来搞定数据,数据库也是来源于之前的项目,这里直接使用了,在服务器,我用IIS来承载WCF,在WCF中使用实体框架edmx,先添加所需项

WCF服务

 SilverLight之路(四)

实体模型

 SilverLight之路(四)

然后选择从数据库生成,新建到数据库的连接

 SilverLight之路(四)

从数据库表中选择我们需要的表

 SilverLight之路(四)

F6编译一下,然后我们在我们的项目中添加对WCF服务的引用,如

 SilverLight之路(四)

现在,我们的项目结构如

 SilverLight之路(四)

这些基本都是自动生成的,不用管它,编译完全没有问题,现在我们添加我们需要的服务

  
    
[ServiceContract]

public interface IWcfService

{

/// <summary>

/// 获取风险测试题

/// </summary>

/// <returns></returns>

[OperationContract]

List
< TB_SYS_DangerTestQuestions > GetRiskTest();

}



public class WcfService : IWcfService

{

public List < DAL.TB_SYS_DangerTestQuestions > GetRiskTest()

{

using (var entities = new DAL.WFT_101104Entities())

{

var q
= entities.TB_SYS_DangerTestQuestions.ToList();

return q;

}

}

}

在风险测试模块的测试题列表页

 

  
    
WcfService.WcfServiceClient client = new WcfService.WcfServiceClient();

void RiskTestPage_Loaded( object sender, RoutedEventArgs e)

{

client.GetRiskTestCompleted
+= new EventHandler < WcfService.GetRiskTestCompletedEventArgs > (client_GetRiskTestCompleted);

client.GetRiskTestAsync();

}



void client_GetRiskTestCompleted( object sender, WcfService.GetRiskTestCompletedEventArgs e)

{

result
= e.Result;

this .icRiskQ.ItemsSource = result.Where(o => string .Compare(o.PID, " 0 " ) == 0 ).ToList();

}

 

运行下看看吧,出错了,在 .xap 应用程序包中无法找到“ServiceReferences.ClientConfig”。

嗯,动态加载的问题,因为模块被动态加载后,程序读的xap包就是主程序的XAP包了,所以提示说找不到配置文件,那我们只要在主程序中添加同一个WCF服务的引用,并使用同一个名称就可以。(正常应用中,也建议把服务引用统一放置,而不是每个项目都去添加服务引用)

现在再试,题目出来了,但接下来的实现可就花费了我好长的时间,按照传统,在ItemControl控件的ItemTemplete中,我再加入一个ItemControl,然后开始寻找印象中的ItemDataBound事件。。。没有!没关系,没有这个事件,那我就在子控件的load事件中绑定,哈哈,轻易搞定!(这里需要借助控件的Tag属性)

  
    
private void icRiskA_Loaded( object sender, System.Windows.RoutedEventArgs e)

{

ItemsControl ic
= sender as ItemsControl;

ic.ItemsSource
= result.Where(o => string .Compare(o.PID, ic.Tag.ToString()) == 0 ).ToList();

}

但这还没完,试着点点看看,不错,还没有提定RadioButton的分组,这个也好办,绑定PID就行了,但真正的问题来,当我试图取每道题的结果时,我没有办法了。。。

网上疯狂寻找办法,参考这个贴子

http://www.cnblogs.com/wackelbh/archive/2010/11/12/1984043.html

那么我们如何获取DataTemplate中的名为txtIDTextBox控件或者其它控件呢?

      test.xaml.cs文件中不能够直接引用名为txtIDTextBox控件,即this.txtID是不能访问的,因为txtID只属于DataTemplate模板的名称空间范围内(类似于参数的作用域),可参看Silverlight4文档的TemplatePartAtrribute 

对于

TextBox txtBox = (TextBox)VisualTreeHelper.GetChild(this.cmbTemplate.LoadContent(), 0);

因为它的Text的值是绑定数据源的ID属性(如:{Binding Path=ID}),通过程序运行动态生成的值,因此通过这两种方式获得的TextBoxText是空值,而对于tbCategoryName名的TextBlock,因为它的Text值是固定的“Name”字符串,因此通过这两种方法获得的TextBlockText值为“Name”

 

总之,我也没找到更好的实现,那就由了它吧,我也换ListBox了,这个例子网上就好多了,我直接给出代码了

View Code
   
     
< ItemsControl x:Name ="icRiskQ" Margin ="20" >

< ItemsControl.Template >

< ControlTemplate >

< ItemsPresenter Margin ="0,0,2,2" />

</ ControlTemplate >

</ ItemsControl.Template >

< ItemsControl.ItemTemplate >

< DataTemplate x:Name ="icRiskQDT" >

< StackPanel >

< StackPanel Orientation ="Horizontal" >

< Image Source ="/Images/ico01.jpg" Stretch ="Fill" VerticalAlignment ="Center" />

< TextBlock x:Name ="textBlock" FontSize ="12"

Text
=" {Binding ItemText} " Foreground ="#FFD2CDCD" d:LayoutOverrides ="Width" />

</ StackPanel >

< ListBox x:Name ="lbRiskA" Tag =" {Binding GUID} " Loaded ="icRiskA_Loaded" Margin ="20,0,0,0" Background =" {x:Null} " BorderThickness ="0" >

< ListBox.ItemTemplate >

< DataTemplate >

< TextBlock Text =" {Binding ItemText} " Tag =" {Binding ItemValue} " Foreground ="#FFD2CDCD" />

</ DataTemplate >

</ ListBox.ItemTemplate >

< ListBox.ItemContainerStyle >

< Style TargetType ="ListBoxItem" >

< Setter Property ="Template" >

< Setter.Value >

< ControlTemplate TargetType ="ListBoxItem" >

< Grid Background ="Transparent" HorizontalAlignment ="Left" VerticalAlignment ="Center" >

< RadioButton IsChecked =" {TemplateBinding IsSelected} " IsHitTestVisible ="False" >

< ContentPresenter />

</ RadioButton >

</ Grid >

</ ControlTemplate >

</ Setter.Value >

</ Setter >

</ Style >

</ ListBox.ItemContainerStyle >

</ ListBox >

</ StackPanel >

</ DataTemplate >

</ ItemsControl.ItemTemplate >

</ ItemsControl >

这里有个建议,虽然读xaml代码会帮助理解,但千万不要陷入xaml的海洋,能用工具还是用工具吧,比如blend。

这样,我们取值时就好办多了,而且有需要可还以做到选择验证,并且让ScrollView定位到具体题目位置(这个我也是找了好半天才找到的,sl的中文资料还是太少了。。。)

  
    
for ( int i = 0 ; i < this .icRiskQ.Items.Count; i ++ )

{

var o
= this .icRiskQ.ItemContainerGenerator.ContainerFromIndex(i);

StackPanel sp
= (StackPanel)VisualTreeHelper.GetChild(o, 0 );

ListBox lb
= (ListBox)sp.FindName( " lbRiskA " );

var q
= lb.SelectedItem as WcfService.TB_SYS_DangerTestQuestions;

if (q == null )

{

MessageBox.Show(
" null answer! " );

var gt
= sp.TransformToVisual( this .mp.SVMain);

Point position
= gt.Transform( new Point( 0 , 0 ));



this .mp.SVMain.ScrollToVerticalOffset( this .mp.SVMain.ScrollableHeight + position.Y);

return ;

}

else

{

allvalue
+= q.ItemValue.Value;

}

}

你可能感兴趣的:(silverlight)