【问题标题】:WPF MVVM User Control binding problemWPF MVVM用户控件绑定问题
【发布时间】:2011-04-07 03:52:23
【问题描述】:

我有一个 wpf mvvm 应用程序。我尝试编写复选框列表控件。
我可以绑定复选框列表元素。
添加到此问题中,我想获取所选复选框列表元素值的总和。
我添加了 DependencyProperty 并将其绑定到视图模型属性。
但是,他们不会互相开火。

CheckBoxList 用户控件 Xaml

<ListBox x:Name="ItemsControl" ItemsSource="{Binding}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <CheckBox Content="{Binding Text}" IsChecked="{Binding IsSelected, Mode=TwoWay}" 
                      Checked="CheckBox_Checked" Unchecked="CheckBox_Checked" />
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

CheckBoxList 背后的代码

public partial class CheckBoxList : UserControl
{
    public CheckBoxList()
    {
        InitializeComponent();
    }

    public static readonly DependencyProperty SelectedCheckBoxItemsValueProperty =
        DependencyProperty.Register("SelectedCheckBoxItemsValue", typeof(int), typeof(CheckBoxList),
            new FrameworkPropertyMetadata(
                0,
                new FrameworkPropertyMetadata(0, OnSelectedItemsChanged));

    public int SelectedCheckBoxItemsValue
    {
        get { return (int)GetValue(SelectedCheckBoxItemsValueProperty); }
        set { SetValue(SelectedCheckBoxItemsValueProperty, value); }
    }

    private static int GetSelectedCheckBoxItemsValue(DependencyObject obj)
    {
        return (int)obj.GetValue(SelectedCheckBoxItemsValueProperty);
    }

    private static void OnSelectedItemsChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
    {
        CheckBoxList checkboxList = obj as CheckBoxList;
        ObservableCollection<ISelectableItem> items = checkboxList.DataContext as ObservableCollection<ISelectableItem>;

        foreach (var item in items)
        {
            item.IsSelected = (GetSelectedCheckBoxItemsValue(obj) & item.Value) != 0;
        }
    }

    private void CheckBox_Checked(object sender, RoutedEventArgs e)
    {
        CheckBoxList checkboxList = sender as CheckBoxList;
        ObservableCollection<ISelectableItem> coll = ItemsControl.DataContext as ObservableCollection<ISelectableItem>;
        if (coll == null) return;

        int count = 0;
        foreach (var item in coll)
        {
            if (item.IsSelected)
            {
                count += item.Value;
            }
        }

        SelectedCheckBoxItemsValue = count;
    }
}

SelectableItem 类

public interface ISelectableItem : INotifyPropertyChanged
{
    bool IsSelected { get; set; }
    string Text { get; set; }
    int Value { get; set; }
    string GroupName { get; set; }
}

public class SelectableItem : ISelectableItem
{ ....

ViewModel 属性

    public int SelectedCheckBoxEnumItemsValue
    {
        get
        {
            return _selectedCheckBoxEnumItemsValue;
        }
        set
        {
            _selectedCheckBoxEnumItemsValue = value;
            NotifyOfPropertyChange("SelectedCheckBoxEnumItemsValue");
        }
    }

在 Binder 课上

        string selectedItemPropertyName = "Selected" + viewModelProperty.Name + "Value";
        var property = viewModelProperties.FirstOrDefault(p => p.Name.Contains(selectedItemPropertyName));

        if (property != null)
        {
            var selectedItemOrValueBinding = new Binding(property.Name)
            {
                Mode = property.CanWrite ? BindingMode.TwoWay : BindingMode.OneWay,
                ValidatesOnDataErrors = Attribute.GetCustomAttributes(property, typeof(ValidationAttribute), true).Any()
            };

            BindingOperations.SetBinding(control, CheckBoxList.SelectedCheckBoxItemsValueProperty, selectedItemOrValueBinding);
        }

【问题讨论】:

    标签: wpf mvvm binding


    【解决方案1】:

    下面的代码解决了你的问题..

    请注意视图模型的分离。

    <StackPanel>
                <TextBlock Text="{Binding Count}"></TextBlock>
                <ListBox x:Name="ItemsControl" ItemsSource="{Binding CheckList}">
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <CheckBox Name="item" Content="{Binding Text}" IsChecked="{Binding IsSelected, Mode=TwoWay}"  Command="{Binding CheckboxCheckedCommand}" CommandParameter="{Binding IsChecked, ElementName=item}"/>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>
    
            </StackPanel>    
    
    
    
    
         public partial class MainWindow : Window
            {
                public MainWindow()
                {
                    InitializeComponent();
                    DataContext = new MasterViewModel();
                }
             }
    
    
    
    
    public class MasterViewModel : INotifyPropertyChanged
    {
        private List<CheckBoxItem> checkList;
        private int count;
    
        public int Count
        {
            get
            {
                return count;
            }
            set
            {
                count = value;
                OnPropertyChanged("Count");
            }
        }
        public List<CheckBoxItem> CheckList
        {
            get
            {
                return checkList;
            }
            set
            {
                checkList = value;
                OnPropertyChanged("CheckList");
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;
    
        public MasterViewModel()
        {
            checkList = new List<CheckBoxItem>();
            for (int i = 0; i < 5; i++)
            {
                CheckBoxItem item = new CheckBoxItem();
                item.Text = i.ToString();
                item.IsSelected = false;
                item.CheckboxCheckedCommand = new RelayCommand(new Action<object>(ExecuteCheckCommand));
                checkList.Add(item);
            }
    
        }
        private void ExecuteCheckCommand(object parameter)
        {
            if (parameter.GetType() == typeof(bool))
            {
                bool value = bool.Parse(parameter.ToString());
                int val = count;
                if (value)
                {     
                    val++;                                   
                }
                else
                {
                    val--;
                }
                Count = val;
            }
        }
    
        private void OnPropertyChanged(string p)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(p));
            }
        }
    }
    
    public class CheckBoxItem : INotifyPropertyChanged
    {
        private bool isSelected;
        private string text;
    
        public string Text
        {
            get 
            {
                return text;
            }
            set
            {
                text = value;
                OnPropertyChanged("Text");
            }
        }
        public bool IsSelected
        {
            get
            {
                return isSelected;
            }
            set
            {
                isSelected = value;
                OnPropertyChanged("IsSelected");
            }
        }
    
        public ICommand CheckboxCheckedCommand
        {
            get;
            set;
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
    
        private void OnPropertyChanged(string p)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(p));
            }
        }
    }
    
    public class RelayCommand : ICommand
    {
        private Action<object> executeCommand;
    
        public RelayCommand(Action<object> executeCommand)
        {
            this.executeCommand = executeCommand;
        }
    
        public bool CanExecute(object parameter)
        {
            return true;
        }
    
        public event EventHandler CanExecuteChanged;
    
        public void Execute(object parameter)
        {
            executeCommand(parameter);
        }
    }
    

    【讨论】:

    • 如果上述解决方案解决了您的问题,请将其标记为答案。是的,首先尝试为您的控制定义责任。尝试参考有关 MVVM 的文章,它们将提高您对 WPF 的理解。参考您的代码,我发现了许多问题,首先是需要创建控件。
    猜你喜欢
    • 2010-12-15
    • 1970-01-01
    • 2010-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多