向ObservableCollection添加其他控件

时间:2012-10-09 21:57:57

标签: c# wpf

我是WPF的新手,如果这是一个显而易见的问题,那就道歉了。我在XAML中有一个简单的Checkbox

<ListBox ScrollViewer.VerticalScrollBarVisibility="Auto" 
ItemsSource="{Binding Selections}" >
    <ListBox.ItemTemplate>
            <DataTemplate>
                    <Grid >
                    <CheckBox IsChecked="{Binding IsChecked}" 
                       Content="{Binding Path=Item.SelectionName}" />
                    </Grid >  
            </DataTemplate>
        </ListBox.ItemTemplate>
</ListBox>

允许绑定和INotifyPropertyChanged的简化代码是:

public ObservableCollection<CheckedListItem<Selection>> Selections { get; set; }

public class Selection
{
    public String SelectionName { get; set; }
}

  Selections = new ObservableCollection<CheckedListItem<Selection>>();
  Selections.Add(new CheckedListItem<Selection>(new Selection() 
         { SelectionName = "SomeName" }, isChecked: true));

    public class CheckedListItem<T> : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private bool isChecked;
        private T item;

        public CheckedListItem()
        { }

        public CheckedListItem(T item, bool isChecked = false)
        {
            this.item = item;
            this.isChecked = isChecked;
        }

        public T Item
        {
            get { return item; }
            set
            {
                item = value;
                if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("Item"));
            }
        }


        public bool IsChecked
        {
            get { return isChecked; }
            set
            {
                isChecked = value;
                if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("IsChecked"));
            }
        }
    }

我现在需要添加一个与每个Checkbox关联的附加TextBox,所以在XAML中我有

    <ListBox ScrollViewer.VerticalScrollBarVisibility="Auto" 
           ItemsSource="{Binding Selections}" Margin="12,22,12,94">
    <ListBox.ItemTemplate>
            <DataTemplate>
                    <Grid >
                    <CheckBox IsChecked="{Binding IsChecked}" 
                       Content="{Binding Path=Item.SelectionName}" />
                    <<TextBox />
                    </Grid >  
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

我有点难过如何将它作为ObservableCollection的一部分包含在内,并在CheckBox和相关的TextBox上设置它的绑定?两者都是使用Selections.Add(new CheckedListItem<Selection>(new Selection() { SelectionName = "SomeName" }, isChecked: true));加在一起的,这让我有些困惑。

编辑:添加完整代码

public partial class SelectionSettingWindow : Window
    {

        public ObservableCollection<CheckedListItem<Selection>> Selections { get; set; }

        public class Selection
        {
            public String SelectionName { get; set; }
            public string SelectionTextField { get; set; }
        }

        public SelectionSettingWindow()
        {
            InitializeComponent();

            Selections = new ObservableCollection<CheckedListItem<Selection>>();
            string fg = @"Item1,true,TExtbox1text:Item2,true,TExtbox2text:Item3,false,TExtbox3text"; //Test String
            string[] splitSelections = fg.Split(':');
            foreach (string item in splitSelections)
            {
                string[] spSelectionSetting = item.Split(',');

                bool bchecked = bool.Parse(spSelectionSetting[1].ToString());
                string tbText = spSelectionSetting[2].ToString();
                Selections.Add(new CheckedListItem<Selection>(new Selection() 
                   { SelectionName = spSelectionSetting[0].ToString(),   
                       SelectionTextField = bText }, isChecked: bchecked));

            }

            DataContext = this;
        }

        public class CheckedListItem<T> : INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;

            private bool isChecked;
            private T item;
            private string textField;

            public CheckedListItem()
            { }

            public CheckedListItem(T item, bool isChecked = false)
            {
                this.item = item;
                this.isChecked = isChecked;
            }

            public T Item
            {
                get { return item; }
                set
                {
                    item = value;
                    if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("Item"));
                }
            }


            public bool IsChecked
            {
                get { return isChecked; }
                set
                {
                    isChecked = value;
                    if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("IsChecked"));
                }
            }

            public string TextField
            {
                get { return textField; }
                set
                {
                    textField = value;
                    if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("TextField"));
                }
            }
        }
}

1 个答案:

答案 0 :(得分:2)

<ListBox ScrollViewer.VerticalScrollBarVisibility="Auto" 
       ItemsSource="{Binding Selections}" Margin="12,22,12,94">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <CheckBox IsChecked="{Binding IsChecked, Mode=TwoWay}" 
                   Content="{Binding Path=Item.SelectionName}" />
                <TextBox Text="{Binding Item.SelectionTextField, Mode=TwoWay}" />
            </StackPanel>  
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

使用SelectionTextField类上的文本框,将上面的Selection替换为需要编辑的字段。

请注意,我将<Grid>更改为<StackPanel>因此它们不会出现在彼此之上并将绑定更改为TwoWay,因此更改会反映在模型中。

确保您的Selection类实现INotifyPropertyChanged(ObservableCollection在集合中添加/删除内容时更新UI,它不知道何时内容的属性发生变化,因此需要自己这样做)

在许多类上实现INotifyPropertyChanged可能很麻烦。我发现实现一个对此有用的基类。我已经得到了这个以及一个额外的反射帮助器,用于提升属性已更改heresnippet我已经可用。它是银光,但它应该适用于WPF。使用我通过下载提供的代码,您只需键入proprpc并点击选项卡,visual studio将存储在通知更改的属性中。我的一篇旧帖子here中有一些解释,并说明我基于代码和代码段的位置。