WPF MVVM用户控件绑定问题

时间:2010-09-02 06:31:15

标签: wpf mvvm binding

我有一个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);
        }

1 个答案:

答案 0 :(得分:0)

以下代码解决了您的问题..

请注意视图模型的隔离。

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