我是银光的新手。我正在尝试生成一个复选框列表(包含内容)。想法是用户将选择其中一些复选框并按下按钮。然后我们尝试读取所选复选框的内容以进行进一步处理。我不知道会有多少个复选框,因此我无法使用绑定。 这是.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上查看以前的问题,但找不到任何答案。请指导我正确的方向。
答案 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用于父项及其子项。
然后,为了允许编辑(您的删除操作),需要确定父节点来自子节点的人,以及获取复选框的状态。
该标识要求我们将初始数据投影到包装类中以便于绑定/识别。
让我解释一下。
假设我们的数据显示顶级姓氏以及与姓氏相关的所有名字。
以上模拟了从数据库中检索到的以下数据类的顶级复选框(删除全部)和子复选框(以删除单个项目):
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事件。我使用一个消息框来显示我已找到正确的项目。例如,如果单击“全部删除”复选框,则会标识子项和复选框的状态,如果单击某个子项,则会标识其父项及其自身。
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")
));
}
}
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中测试更容易/更快。