属性绑定在ListBox WPF中不起作用

时间:2016-04-26 15:07:25

标签: c# wpf xaml data-binding listbox

我正在尝试使用包含复选框和文本块的网格组成的项目填充ListBox。我最初只有一个复选框,但我需要将文本换行,所以我将其更改为带有复选框和文本块的网格,文本块执行文本换行。

当它只是复选框时,绑定工作,但现在它没有。现在,列表框中显示正确的项目数,但它只是一个未选中的复选框(即使我将其设置为后面的代码中检查,见下文)和一个空白文本块。

XAML:

<ListBox 
    x:Name="lstCalibration" 
    Margin="304,95,78,24" 
    Background="#7FFFFFFF" 
    Width="211" 
    HorizontalAlignment="Center" 
    VerticalContentAlignment="Stretch" 
    ScrollViewer.HorizontalScrollBarVisibility="Disabled" 
    HorizontalContentAlignment="Stretch">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Grid Width="auto">
                <Grid.RowDefinitions>
                    <RowDefinition Height="auto"/>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="auto"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <CheckBox 
                    Content="" 
                    Tag="{Binding Tag}" 
                    IsChecked="{Binding IsChecked}" 
                    Checked="CheckBoxCal_Checked" 
                    Unchecked="CheckBoxCal_Unchecked"
                    Grid.Row="0" Grid.Column="0"
                    />
                <TextBlock 
                    Tag="{Binding Tag}" 
                    Text="{Binding Text}" 
                    TextWrapping="Wrap"
                    Grid.Row="0" 
                    Grid.Column="1"
                    />
            </Grid>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

代码背后:

foreach (Controller item in calList)
{
    //fill listbox with cals and correct checked states
    Grid grid = new Grid();
    CheckBox cb = new CheckBox();
    TextBlock tb = new TextBlock();
    tb.Text = item.Description;
    cb.Tag = tb.Tag = i;
    cb.IsChecked = calChecked[i];
    if (cb.IsChecked == true)
        noneChecked = false;
    i++;

    Grid.SetRow(cb, 0);
    Grid.SetColumn(cb, 0);
    grid.Children.Add(cb);
    Grid.SetRow(tb, 0);
    Grid.SetColumn(tb, 1);
    grid.Children.Add(tb);
    lstCalibration.Items.Add(grid);
}

1 个答案:

答案 0 :(得分:1)

添加此项,并删除该foreach循环,您可以以编程方式创建已在DataTemplate中设置的所有内容。这是一个非常好的DataTemplate,但你的代码没有正确使用它。 摆脱calChecked; _items[n].IsChecked现在将完成这项工作。

您可以随时向ListItem添加新的_items,它会显示在列表中,或删除现有的PropertyChanged,它将从列表中消失。那是“可观察的”部分。感谢IsChecked事件提升,如果您从后面的代码中设置public class ListItem : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; public String Text { get; set; } private bool _isChecked = false; public bool IsChecked { get { return _isChecked; } set { _isChecked = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsChecked)); } } } ,则UI中的相应复选框将自动更新。

private ObservableCollection<ListItem> _items;
public MyWindow()
{
    InitializeComponent()

    _items = new ObservableCollection<ListItem>(
        calList.Select(
            cal => new ListItem {
                       Text = cal.Description,
                       IsChecked = cal.WhateverElse
                   }
        ));

    lstCalibration.Items = _items;
}

在代码后面的构造函数中:

DataTemplate

在两个地方对Tag进行一次小改动:不要浪费时间约束public void CheckBoxCal_Checked(object sender, EventArgs args) { var listItem = ((FrameworkElement)sender).DataContext as ListItem; // Do whatever. listItem.IsChecked will be up to date thanks // to the binding. } 。在事件处理程序(你甚至可能不需要)中,只需这样投射:

            <CheckBox 
                Content="" 
                IsChecked="{Binding IsChecked}" 
                Checked="CheckBoxCal_Checked" 
                Unchecked="CheckBoxCal_Unchecked"
                Grid.Row="0" Grid.Column="0"
                />
            <TextBlock 
                Text="{Binding Text}" 
                TextWrapping="Wrap"
                Grid.Row="0" 
                Grid.Column="1"
                />

XAML:

postgres=# create table t (x int );
CREATE TABLE
postgres=# insert into t values (1);
INSERT 0 1
postgres=# insert into t values (NULL);
INSERT 0 1
postgres=# insert into t values (3);
INSERT 0 1
postgres=# select * from t;
 x
---
 1

 3
(3 rows)

postgres=# select (CASE WHEN x is NULL THEN 0 ELSE x END) from t;
 x
---
 1
 0
 3
(3 rows)