如何在单个控件中绑定命令和数据?

时间:2014-09-13 21:18:00

标签: c# asp.net-mvc wpf data-binding user-controls

我正在为项目编写自定义控件。该控件将包含下拉组合框和数据网格。该控件将在整个项目中使用。在控件上,我将SelectedDate和SelectedDateChangedCommand作为依赖项属性公开。当用户选择日期时,主程序模型将更新其相关日期的信息列表。

当我在项目中使用该控件时,数据(SelectedDate)应来自模型,但命令(SelectedDateChangedCommand)应来自ViewModel。如何将数据绑定到Model和ViewModel的命令?

基本上,如果我想绑定同一个按钮的内容AND命令,我该怎么办?

修改 好吧,我不认为我能很好地解释这一点。我没有使用框架或模板或类似的东西。也许我的问题是提到UserControl。我的问题不在于编写UserControl。我的问题来自控制之外。我没有代码示例,因为这是我的问题:我该怎么做?如果我有某种代码,那就像这样:

<Button Content="{Binding Model.SelectedDate]" Command="{Binding ViewModel.SelectedDateChanged}" />

如何在两个不同类的控件上绑定两个属性?

哇,甚至询问问题在WPF中都很难。 :)

1 个答案:

答案 0 :(得分:0)

好的,如果我了解你,你想创建一个cc。然后在你的vm上运行绑定到DateTime到你的SelectedDate,并从控件到vm调用命令?我在这里为你做了一个简单的例子,我希望我能正确理解你。我通过使用datepicker简化了这个例子。我在这里使用galasoft MVVM Light。将内容更改为您想要的内容。希望我没有让你完全错误:)

<强> Generic.xaml

<Style TargetType="{x:Type local:YourCustControl}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:YourCustControl}">
                <Border Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}">
                    <Grid >
                        <DatePicker x:Name="PART_DatePicker"
                           SelectedDate="{Binding Path=YourDateTime, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, 
                            RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:YourCustControl}}}"/>
                    </Grid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<强> CustControl

[TemplatePart(Name = "PART_DatePicker", Type = typeof (DatePicker))]
public class YourCustControl : Control
{
    public static readonly DependencyProperty SelectedDateChangedCommandProperty = DependencyProperty.Register("SelectedDateChangedCommand", typeof (ICommand), typeof (YourCustControl), new PropertyMetadata(null));
    public static readonly DependencyProperty YourDateTimeProperty = DependencyProperty.Register("YourDateTime", typeof (DateTime), typeof (YourCustControl), new PropertyMetadata(null));
    private DatePicker datePicker;

    static YourCustControl()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof (YourCustControl), new FrameworkPropertyMetadata(typeof (YourCustControl)));
    }

    public ICommand SelectedDateChangedCommand
    {
        get { return (ICommand) GetValue(SelectedDateChangedCommandProperty); }
        set { SetValue(SelectedDateChangedCommandProperty, value); }
    }

    public DateTime YourDateTime
    {
        get { return (DateTime) GetValue(YourDateTimeProperty); }
        set { SetValue(YourDateTimeProperty, value); }
    }

    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();

        datePicker = (DatePicker) Template.FindName("PART_DatePicker", this);
        if (datePicker != null)
        {
            datePicker.SelectedDateChanged += datePicker_SelectedDateChanged;
        }
    }

    private void datePicker_SelectedDateChanged(object sender, SelectionChangedEventArgs e)
    {
        // Execute the command
        if (SelectedDateChangedCommand != null && SelectedDateChangedCommand.CanExecute(e) && !e.Handled)
            SelectedDateChangedCommand.Execute(e);
    }
}

<强>视图模型

// replace with whatever, like extend Galasoft's ViewModelBase 
public class YourViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator] // Remove if no R#
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

public class YourViewModel : YourViewModelBase
{
    private DateTime dateTime;

    public DateTime DateTime
    {
        get { return dateTime; }
        set
        {
            if (value.Equals(dateTime)) return;
            dateTime = value;
            OnPropertyChanged();
        }
    }

    public ICommand SelectedDateChangedCommand { get; set; }

    public YourViewModel()
    {
        SelectedDateChangedCommand = new RelayCommand<SelectionChangedEventArgs>(OnSelectedDateChanged);
    }

    private void OnSelectedDateChanged(SelectionChangedEventArgs e)
    {
        if (e != null)
            e.Handled = true; // dirty hack
        // do stuff here
    }
}

最后你的xaml

<Grid>
    <local:YourCustControl SelectedDateChangedCommand="{Binding SelectedDateChangedCommand}" 
                           YourDateTime="{Binding DateTime, Mode=TwoWay}"/>
</Grid>

希望它有所帮助!

干杯