属性绑定在ListBox WPF中不起作用 [英] Property binding not working in ListBox WPF

查看:82
本文介绍了属性绑定在ListBox WPF中不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图用一个包含一个复选框和一个文本块的网格组成的项目填充一个ListBox.我最初只有一个复选框,但是我需要包装文本,因此我将其更改为带有复选框和文本块的网格,其中文本块进行了文本包装.

I am trying to fill a ListBox with items consisting of a grid which holds a checkbox and a textblock. I originally had only a checkbox but I need the text to wrap so I changed it to a grid with a checkbox and a textblock, with the text block doing the text wrapping.

当只是复选框时,绑定起作用,但现在不起作用.现在,正确数量的项目显示在列表框中,但这只是一个未选中的复选框(即使我将其设置为在后面的代码中选中,请参见下文)和一个空白的文本块.

When it was just the the checkbox, the binding worked, but now it does not. Now the correct number of items show up in the listbox but it is just an unchecked checkbox (even if I set it to checked in the code behind, see below) and a blank textblock.

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);
}

推荐答案

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

Add this, and delete that foreach loop where you programatically create all the stuff you already set up in your DataTemplate. It's a perfectly good DataTemplate, but your code isn't using it right. Get rid of calChecked; _items[n].IsChecked will now do that job.

您随时可以向_items添加新的ListItem,它会出现在列表中,或者删除现有的ListItem,它会从列表中消失.那是可观察的"部分.由于引发了PropertyChanged事件,如果您从后面的代码中对任何一个设置了IsChecked,则UI中的相应复选框都会自动更新.

At any time you can add a new ListItem to _items and it will appear in the list, or remove an existing one and it will vanish from the list. That's the "observable" part. Thanks to the PropertyChanged event raising, if you set IsChecked on any of these from code behind, the corresponding checkbox in the UI will automagically update.

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));
        }
    }
}

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

In your constructor in code behind:

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.在事件处理程序中(您甚至可能不需要),只需像这样进行投射:

One small change to DataTemplate in two places: Don't waste time binding Tag. In the event handlers (which you may not even need), just cast like so:

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.
}

XAML:

            <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"
                />

这篇关于属性绑定在ListBox WPF中不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆