listbox是在DataTemplate中选择数据绑定

时间:2012-09-17 20:53:19

标签: c# xaml data-binding wpf-controls datatemplate

我尝试在我的班级中使用IsSelected字段简单地数据绑定IsSelected属性。但是在我更改代码中的值后,它不会更改属性,也不会单击ListBoxItem更改字段值。

XAML:

<FlipView ItemsSource="{Binding Source={StaticResource itemsViewSource}}" ... >
    <FlipView.ItemTemplate>
        <DataTemplate>
            <UserControl Loaded="StartLayoutUpdates" 
                Unloaded="StopLayoutUpdates">
                <!-- other controls -->
                <ListBox Grid.Row="1" Grid.ColumnSpan="3"
                    SelectionMode="Multiple" VerticalAlignment="Center" 
                    ItemsSource="{Binding Answers}">
                    <ListBox.Resources>
                        <local:LogicToText x:Key="logToText" />
                    </ListBox.Resources>

                     <!-- bind IsSelected only in one way from 
                         code to content --> 
                     <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <ListBoxItem 
                              IsSelected="{Binding IsSelected, Mode=TwoWay, Converter={StaticResource logToText}}" 
                              Content="{Binding IsSelected, Mode=TwoWay, Converter={StaticResource logToText}}">

                            </ListBoxItem>

                        </DataTemplate>
                    </ItemsControl.ItemTemplate>


                    <!-- not working at all
                    <ListBox.Resources>
                        <Style TargetType="ListBoxItem">
                            <Setter Property="IsSelected" 
                                Value="{Binding IsSelected, Mode=TwoWay}"/>
                            <Setter Property="Content" 
                                Value="{Binding IsSelected, Mode=TwoWay}"/>
                        </Style>
                    </ListBox.Resources>-->

                </ListBox>
            </UserControl>
        </DataTemplate>
    </FlipView.ItemTemplate>
</FlipView>

代码:

答案

private ObservableCollection<PrawoJazdyDataAnswer> _answers = 
    new ObservableCollection<PrawoJazdyDataAnswer>();
public ObservableCollection<PrawoJazdyDataAnswer> Answers 
{ 
    get 
    { 
       return this._answers; 
    }  
}    

单项(答案)

public class PrawoJazdyDataAnswer : NPCHelper// PrawoJazdy.Common.BindableBase
{
    public PrawoJazdyDataAnswer(String ans, bool ansb)
    {
        this._ans = ans;
        this._isSelected = ansb;
    }

    public override string ToString() 
    { 
        return _isSelected.ToString();  //Only For debug purposes 
                                        //normally return _ans 
    }
    private string _ans;
    public string Ans
    {
        get { return this._ans; }
        //set { this.SetProperty(ref this._ans, value); }
    }

    private bool _isSelected;
    public bool IsSelected
    {
        get { return this._isSelected; }
        set
        {
            _isSelected = value;
            FirePropertyChanged("IsSelected");
            //this.SetProperty(ref this._isSelected, value); 
        }
    }
}

FirePropertyChanged

public class NPCHelper : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    public void FirePropertyChanged(string prop)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(prop));
    }
}

转换器(有时似乎需要而其他人不需要......,我尝试了来自不同教程/示例的10种方法)

public class LogicToText : IValueConverter
{
    /// <summary>
    /// 
    /// </summary>
    public object Convert(object value, Type targetType, 
                          object parameter, string language)
    {
        //if (value == null || (bool)value == false)
          //  return "False";

        return value.ToString();
    }

    /// <summary>
    /// 
    /// </summary>
    public object ConvertBack(object value, Type targetType, 
                              object parameter, string language)
    {
        return value.ToString().Contains("True") ? true : false;
    }

提前致谢,对不起我的英语(仍在学习)。

@edit 谢谢你快速回复。

出于测试目的,我创建了一个按钮和文本块:

<Button Click="spr" >Sprawdź</Button>
<TextBlock Text="{Binding Answers[0].IsSelected, Mode=TwoWay}" > </TextBlock> 

它在其他控件部分(列表框上方,但在FlipView中) 点击方法

private void spr(object sender, RoutedEventArgs e)
    {
        var ans = ((PrawoJazdyDataQuestion)this.flipView.SelectedItem).Answers;
        foreach (var item in ans)
            item.IsSelected = item.IsSelected ? false : true;
    }

正如我所写,当我从代码端更改数据时,它正在更改元素的内容,而不是ListBoxItem的外观。如果我只是在ListBox上选择它,它就不会更改TextBlock本身ListBox中的数据。

@ edit2修复错别字...

2 个答案:

答案 0 :(得分:8)

要更改IsSelected的{​​{1}}属性,您需要更改ListBoxItem。见这里:

ListBox.ItemContainerStyle

由于绑定模式为<ListBox Grid.Row="1" Grid.ColumnSpan="3" SelectionMode="Multiple" VerticalAlignment="Center" ItemsSource="{Binding Answers}"> <ListBox.ItemContainerStyle> <Style TargetType="ListBoxItem"> <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" /> </Style> </ListBox.ItemContainerStyle> <ListBox.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding IsSelected}" /> </DataTemplate> </ListBox.ItemTemplate> </ListBox> ,因此选择和取消选择TwoWay会动态更改项目的内容,以显示ListBoxItemTrue

另请注意我如何将False更改为ListBox.ItemTemplate而不是TextBlockListBoxItem定义ItemTemplate的内容,因此通常使用某种类型的内容控件。下面是不同布局的UI结构(可以使用WPF树可视化工具查看)。

ListBoxItem作为ListBoxItem

enter image description here

ItemTemplate作为TextBlock

enter image description here

修改

另请注意,我删除了ItemTemplate。由于源属性和目标属性都是IValueConverter,因此在这种情况下不需要转换器。尝试删除转换器引用以查看是否可以解决问题。

答案 1 :(得分:0)

不要绑定到ListBoxItem上的IsSelected。 ListBox有SelectedItem或SelectedItems属性,你应该传递要被选择的项目,即通过绑定。 在模型中设置IsSelected属性并不是一个好主意。最好在ViewModel中使SelectedItem通知属性。