获取Silverlight中xaml.cs中复选框的内容

时间:2015-05-18 21:28:42

标签: xaml silverlight

我是银光的新手。我正在尝试生成一个复选框列表(包含内容)。想法是用户将选择其中一些复选框并按下按钮。然后我们尝试读取所选复选框的内容以进行进一步处理。我不知道会有多少个复选框,因此我无法使用绑定。 这是.xaml文件中的代码段。

<StackPanel Grid.Row="21" Grid.Column="1" Margin="5" VerticalAlignment="Center">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>

        <ItemsControl Name="infoPairItems" ItemsSource="{Binding InfoPair}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <CheckBox Grid.Column="0" Name="infoPairSelectBox" IsEnabled="True" IsThreeState="False" 
                        Margin="0,5" FontSize="12" IsChecked="bool"
                        Content="{Binding Converter={StaticResource infoPairToStringValueConverter}}"/>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </Grid>
</StackPanel>

我试图像这样访问.xaml.cs文件中的这些复选框。

foreach(var infoPairItem in infoPairItems.Items)
{                
    ContentPresenter container = infoPairItems.ItemContainerGenerator.ContainerFromItem(infoPairItem) as ContentPresenter;
    if(container == null)
    {
        DebugLog.Log("container is null ");
    }

    DataTemplate dataTemplate = container.ContentTemplate;                                
    CheckBox checkBox = (CheckBox)dataTemplate.LoadContent();
    if (checkBox == null)
    {
        DebugLog.Log("checkBox is null !!!");
        return;
    }
    if (checkBox.IsChecked.HasValue)
    {
        if (checkBox.IsChecked.Value)
        {
            DebugLog.Log("checkbox value true");
        }
        else
        {
            DebugLog.Log("checkbox value false");
        }
    }
}

日志&#39;复选框值false&#39;即使选择了其中一些复选框,也始终打印所有复选框。我试着使用调试器。看起来变量容器正在加载正确的值。方法LoadContent()不起作用或我使用错误的方法。 如果这是一个重复的问题,我事先道歉。我试着在stackoverflow上查看以前的问题,但找不到任何答案。请指导我正确的方向。

2 个答案:

答案 0 :(得分:1)

我将解释会发生什么以及如何解决:

1.-您正在获取datatemplate而不是datatemplate的实例,以防您想要管理可以通过使用Loaded Event将项添加到List以创建和更新例如List的实例。

2.-如果您创建以下内容,是什么使所有这些事件成为一个非常复杂的代码来管理:

2.1例如,具有bool和INotifyPropertyChanged内容的字符串的类:

public class InfoSelection : Model
{
 Property bool for Selected 
 Property string for Info, or whatever and the converter
}

2.2包含DataContext中该类类型所需项目的列表

public List<InfoSelection> {get;set;}

(例如,如果在构造函数中只初始化一次,则不需要实现INotiyPropertyChanged,只需清除或删除项目,永远不要重新分配)

2.3在Xaml绑定中更改为以下内容:

<CheckBox Grid.Column="0" 
          Name="infoPairSelectBox" 
          IsEnabled="True" 
          IsThreeState="False" 
          Margin="0,5" 
          FontSize="12" 
          IsChecked="{Binding Selected, Mode=TwoWay}" 
          Content="{Binding Info}"/>

答案 1 :(得分:0)

  

我不知道会有多少个复选框,因此我无法使用绑定。

不正确的。

要通过视觉方式显示两个级别的数据,可以使用ItemsControl将单个DataTemplate用于父项及其子项。

然后,为了允许编辑您的删除操作),需要确定父节点来自子节点的人,以及获取复选框的状态。

该标识要求我们将初始数据投影到包装类中以便于绑定/识别。

让我解释一下。

假设我们的数据显示顶级姓氏以及与姓氏相关的所有名字。

enter image description here

以上模拟了从数据库中检索到的以下数据类的顶级复选框(删除全部)和子复选框(以删除单个项目):

public class VectorStrings
{
    public int          Id         { get; set; }
    public string       LastName   { get; set; }
    public List<string> FirstNames { get; set; }
}

模拟数据加载如下:

LastNames = new List<VectorStrings>()
{
    new VectorStrings() { Id=9,  LastName="Smith", FirstNames = new List<string>() { "Bob", "Victoria" } },
    new VectorStrings() { Id=12, LastName="Jones", FirstNames = new List<string>() { "Peter", "Paul", "Mary" } },
};

现在为了显示我可以通常将这些项目显示到上面的数据中,但是因为我们需要对子数据进行操作,所以我们需要这些信息投射到拿着包装类。

public class VectorCheckbox
{
    public int                  Id          { get; set; }
    public int                  ParentId    { get; set; }
    public string               DisplayName { get; set; }
    public List<VectorCheckbox> Children    { get; set; }
    public object Tag { get; set; } // Same concept as a visual control property 'Tag'
}

所以我们的项目原始数据的代码如下所示:

CheckBoxData = 
    LastNames.Select(ln => new VectorCheckbox()
           {
               DisplayName = ln.LastName,
               Id = ln.Id,
               Tag = ln,
               Children = ln.FirstNames.Select((fn, index) => new VectorCheckbox()
               {
                   Id          = index,
                   ParentId    = ln.Id,
                   DisplayName = fn,
                   Tag         = ln.Id // Hold the parent Id for identification
               }).ToList()

         })
            .ToList();

甜!现在我们只需要嵌套的ItemControl类来显示我们的数据:

<ItemsControl  ItemsSource="{Binding CheckBoxData}">
    <ItemsControl.Resources>
        <system:String x:Key="Format">Delete All for ID: '{0}' </system:String>
    </ItemsControl.Resources>
<ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
        <StackPanel Orientation="Vertical" Margin="10" />
    </ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
    <DataTemplate>
            <StackPanel Orientation="Horizontal" Margin="6,0,0,0">
                <CheckBox Tag="{Binding Id}" Margin="0,0,0,10"  Click="DeleteAll_Click">
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="{Binding Id, StringFormat={StaticResource Format}}"/>
                        <TextBlock Text="{Binding DisplayName}" Margin="4,0,6,0"/>
                        <ItemsControl ItemsSource="{Binding Children}">
                            <ItemsControl.ItemTemplate>
                                <DataTemplate>
                                    <CheckBox Tag="{Binding Tag}" 
                                              Content="{Binding DisplayName}" 
                                              Click="DeleteIndividual_Click"/>
                                </DataTemplate>
                            </ItemsControl.ItemTemplate>
                        </ItemsControl>
                    </StackPanel>
                </CheckBox>
            </StackPanel>
    </DataTemplate>
</ItemsControl.ItemTemplate>

现在我们在代码后面订阅了click事件。我使用一个消息框来显示我已找到正确的项目。例如,如果单击“全部删除”复选框,则会标识子项和复选框的状态,如果单击某个子项,则会标识其父项及其自身。

家长点击

Parent has been clicked and message box shown

private void DeleteAll_Click(object sender, RoutedEventArgs e)
{
    var cb = sender as CheckBox;

    if (cb != null)
    {
        var id = (int)cb.Tag;

        var nameInstance = ViewModel.LastNames.FirstOrDefault(nm => nm.Id == id);

        if (nameInstance != null)
            MessageBox.Show(string.Format("Delete all for {0} of names {1} (Status {2})",
            nameInstance.LastName,
            string.Join(",", nameInstance.FirstNames),
            ((cb.IsChecked ?? false) ? "Checked" : "UnChecked")
            ));
    }
}

儿童点击

Child has been clicked

private void DeleteIndividual_Click(object sender, RoutedEventArgs e)
{
    var cb = sender as CheckBox;

    if (cb != null)
    {
        var parentId = (int)cb.Tag; // Parent Id

        var nameInstance = ViewModel.LastNames.FirstOrDefault(nm => nm.Id == parentId);

        if (nameInstance != null)
            MessageBox.Show(string.Format("Delete individual for {0} of name {1} (Status {2})",
            nameInstance.LastName,
            cb.Content,
            ((cb.IsChecked ?? false) ? "Checked" : "UnChecked")
            ));

    }
}

因此,我已经确定了复选框状态以及目标原始项目。此代码最终模拟您要执行的操作。我留下了可观察集合的实际管道,删除了你的项目。但这可以解决这个问题。

我建议您在WPF中进行实验,然后将其带到Silverlight,因为概念是相同的,但在WPF中测试更容易/更快。