0

我对 WPF 真的很陌生,所以如果这是一个明显的问题,我很抱歉。我在 XAML 中有一个简单的复选框

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

我现在需要添加一个与每个复选框关联的附加文本框,所以在 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"));
                }
            }
        }
}
4

1 回答 1

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>为 a<StackPanel>所以它们不会出现在彼此之上,并将绑定更改为 TwoWay,因此更改会反映在模型中。

确保您的Selection类实现INotifyPropertyChanged(ObservableCollection 在将内容添加到集合中/从集合中删除时更新 UI,它不知道何时通知内容的属性发生更改,因此他们需要自己执行此操作)

在许多类上实现INotifyPropertyChanged可能很麻烦。我发现实现一个对此有用的基类。我已经有了这个,还有一个额外的反射帮助器,用于在此处更改可用的 raise 属性,以及我提供的一个片段。它是silverlight,但它应该适用于WPF。使用我通过下载提供的代码,您只需键入proprpc并点击选项卡,Visual Studio 就会存根通知更改的属性。一些解释在我的一篇旧博客文章中并归功于我基于代码和片段的位置。

于 2012-10-09T22:05:25.393 回答