【问题标题】:listbox isSelected databinding in DataTemplateDataTemplate 中的列表框 isSelected 数据绑定
【发布时间】:2012-09-10 02:59:00
【问题描述】:

我尝试在课堂上简单地将 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;
    }

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

@编辑 感谢您的快速回复。

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

<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 修正错别字...

【问题讨论】:

  • 不需要转换器,因为绑定源和目标属性都是bool 类型。不过对我来说一切都很好。您能否发布一些有关如何更新属性的示例代码?

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


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    要更改ListBoxItemIsSelected 属性,您需要更改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,选择和取消选择ListBoxItem 会动态更改项目的内容以显示TrueFalse

    还要注意我是如何将ListBox.ItemTemplate 更改为TextBlock 而不是ListBoxItemItemTemplate 定义了ListBoxItem 的内容,因此通常使用某种类型的内容控件。下面是不同布局的 UI 结构(可以使用 WPF Tree Visualizer 查看)。

    ListBoxItem 作为ItemTemplate:

    TextBlock 作为ItemTemplate

    编辑

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

    【讨论】:

    • 感谢您的回复,但在代码更改后,它仍然以以前的方式工作,文本正在更改,但没有出现选择。
    • @Kinmarui 好的。我的意思是在 PrawoJazdyDataAnswer 类的 IsSelected 属性设置器后面的代码中设置断点。如果绑定设置正确,则当您选择/取消选择列表项时应该触发该设置器。
    • @Kinmarui 那个二传手应该被解雇了。由于某种原因,绑定不起作用。您可以在输出窗口中查看绑定错误(如果您没有看到任何可能需要设置此选项的选项 Tools->Options->Debugging->Output Window->WPF Trace Settings->Data BindingWarning)。此外,here 是我创建的测试项目的所有代码
    • @MeadorDylan 没有错误或警告。非常感谢您尝试帮助我,现在我唯一能想到的是为什么它不起作用,因为listBoxDataTemplate 中,而在您的示例中它不是。现在我尝试通过将SelectedItems 属性与代码隐藏中的另一个集合绑定来解决这个问题。
    猜你喜欢
    • 2020-11-05
    • 1970-01-01
    • 2010-09-19
    • 1970-01-01
    • 2013-06-22
    • 2011-11-20
    • 2012-12-16
    • 2012-11-14
    • 2016-10-13
    相关资源
    最近更新 更多