SilverLight之路(四)

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

如图

 

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

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

  

 

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

WCF服务

 

实体模型

 

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

 

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

 

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

 

现在,我们的项目结构如

 

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

[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;

}

}
原文地址:https://www.cnblogs.com/meteortent/p/2077533.html