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

    }

    }
  • 相关阅读:
    StringBuffer
    判断java标识符
    基本数据类型和String相互转换
    使用String
    Properties属性文件
    Map排序
    java集合之三映射:HashMap、Hashtable、LinkedHashMap、TreeMap
    列表、集合与数组之间相互转换
    自定义列表排序
    ML-支持向量:SVM、SVC、SVR、SMO原理推导及实现
  • 原文地址:https://www.cnblogs.com/meteortent/p/2077533.html
Copyright © 2020-2023  润新知