【问题标题】:WPF MVVM Button Control Binding in DataTemplateDataTemplate 中的 WPF MVVM 按钮控件绑定
【发布时间】:2010-09-22 19:15:15
【问题描述】:

我已经看到其他处理这个问题的问题,但从来没有任何明确的代码描述修复。我无法在我的 ItemTemplate 中获得一个按钮来绑定到任何地方的任何命令。非常令人沮丧。顺便说一句,我是一个完整的 MVVM 新手。

这是我的窗口 XAML。

<Window x:Class="RET.CMS.Printing.App.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:RET.CMS.Printing.App.ViewModel"
    Height="350" Width="525"
    WindowStartupLocation="CenterScreen"
    Title="{Binding Path=DisplayName}"
    >
<Window.Resources>
    <ResourceDictionary Source="MainWindowResources.xaml" />
</Window.Resources>
<Window.DataContext>
    <local:MainWindowViewModel />
</Window.DataContext>

<DockPanel Margin="10">
    <Grid Margin="10" DockPanel.Dock="Top">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1*" />
            <ColumnDefinition Width="1*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition />
        </Grid.RowDefinitions>
        <Image Grid.Column="0" MaxHeight="75" MinHeight="25" HorizontalAlignment="Left"
                   Source="/RET.CMS.Printing.App;component/Resources/BarkleyREI%20%283%29.png" />
        <TextBlock Grid.Column="1" HorizontalAlignment="Right" 
                    Height="30" VerticalAlignment="Top"
                    Style="{StaticResource TBHyperlinkStyle}"
                    >
            Help
        </TextBlock>
    </Grid>

    <Border Padding="10" DockPanel.Dock="Left">
        <DockPanel>
            <Label Style="{StaticResource H1Style}" DockPanel.Dock="Top">YOUR PRINTERS</Label>
            <StackPanel Margin="10" DockPanel.Dock="Top">
                <Button Style="{StaticResource RegularButton}" HorizontalAlignment="Left" Command="{Binding RefreshPrintersCommand}">Refresh List</Button>
            </StackPanel>
                <ListBox ItemsSource="{Binding Printers}" DockPanel.Dock="Left">
                <ListBox.ItemContainerStyle>
                    <Style TargetType="ListBoxItem">
                        <Setter Property="HorizontalContentAlignment" Value="Stretch" />
                    </Style>
                </ListBox.ItemContainerStyle>
                    <ListBox.ItemTemplate>
                <DataTemplate>
                        <Border Padding="5">
                            <StackPanel>
                            <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="*" />
                                    <ColumnDefinition Width="75" />
                                </Grid.ColumnDefinitions>
                                <Grid>
                                    <Grid.RowDefinitions>
                                        <RowDefinition Height="*" />
                                        <RowDefinition Height="*" />
                                    </Grid.RowDefinitions>
                                    <Grid Grid.Row="0">
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="*" />
                                            <ColumnDefinition Width="*" />
                                            <ColumnDefinition Width="50" />
                                        </Grid.ColumnDefinitions>
                                            <TextBlock Style="{StaticResource TBHyperlinkStyle}" Text="{Binding Printer.Name}" Grid.Column="0" Margin="2" />
                                            <TextBlock Text="{Binding Printer.Status}" Grid.Column="1" Margin="2"/>
                                        <Image Grid.Column="2" Margin="2"  />
                                    </Grid>
                                    <TextBlock Text="{Binding Printer.Debug}" Grid.Row="1"/>
                                </Grid>
                            <Button Grid.Column="1" Content="Pause"
                                    Command="{Binding Path=PausePrinterCommand}"
                                    ></Button>
                        </Grid>

                        </StackPanel>
                        </Border>
                    </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
        </DockPanel>
    </Border>

</DockPanel>

这是我的 ViewModel:

 public class MainWindowViewModel:ViewModelBase
{
    #region Fields
    private ObservableCollection<PrinterViewModel> _Printers = new ObservableCollection<PrinterViewModel>();
    #endregion Fields

    #region Properties
    public ObservableCollection<PrinterViewModel> Printers
    {
        get
        {
            if(_Printers==null)
                LoadPrinters();
            return _Printers;
        }
    }
    #endregion Properties

    #region Constructor
    public MainWindowViewModel()
    {
        base.DisplayName = Resources.MainWindowViewModel_DisplayName;

        //bind commands
        RefreshPrintersCommand = new RelayCommand(param =>this.LoadPrinters());
        PausePrinterCommand = new RelayCommand( param => this.PausePrinter(param));
    }
    #endregion Constructor
    #region Private Members

    private void LoadPrinters()
    {
        PrintersRepository pr = new PrintersRepository(Config.SettingsLoader.GetPrintServers());
        _Printers.Clear();
        pr.GetPrinters().ForEach(i =>
            _Printers.Add(new PrinterViewModel(i)));
        OnPropertyChanged("Printers");
    }
    private void PausePrinter(object printerFullName)
    {
        var p = _Printers.Where(i => i.Printer.FullName == printerFullName as string);
    }
    #endregion Private Members

    #region Commands
    public ICommand RefreshPrintersCommand
    {
        get;
        private set;
    }
    public ICommand PausePrinterCommand
    {
        get;
        private set;
    }

    #endregion Commands
}

这是我的 PrinterViewModel:

 public class PrinterViewModel:ViewModelBase
{
    private Printer _Printer;

    private RelayCommand _PauseCommand;
    public PrinterViewModel(Printer p)
    {
        _Printer = p;

    }
    public Printer Printer { get { return _Printer; } }

    public RelayCommand PauseCommand
    {
        get
        {
            if (_PauseCommand == null)
                _PauseCommand = new RelayCommand(param=>_Printer.Pause());
            return _PauseCommand;
        }
    }

}

请帮忙!为什么我不能得到这个?

【问题讨论】:

  • 我要绑定的按钮是 DataTemplate 中带有 PausePrinterCommand 的这个按钮...应该提到
  • 看起来应该可以了。您需要学习如何更好地调试绑定问题。转到 Debug 菜单,点击 Options and Settings,然后选择左侧的 Output Window,然后在 WPF Trace Settings 下将 Dependency Properties 切换为 All。现在调试您的应用程序。观察绑定错误的输出窗口。请注意,使用All 设置您会得到一些误报。但请注意涉及您的按钮的迟到的错误。你应该得到一些关于到底发生了什么的信息。
  • 会 - 非常感谢您向我指出这一点。作为新手,很高兴知道更有经验的 WPF 开发人员正在使用什么技巧。

标签: wpf mvvm binding command


【解决方案1】:

ItemTemplate 中按钮的DataContext 是一个PrinterViewModel 对象(具有PauseCommand)。但是,您正在尝试将 PausePrinterCommand 绑定到它,这是 MainWindowViewModel 的一个属性。

为了完成这项工作(即使用 ItemTemplate 中的按钮执行 MainViewModel.PausePrinterCommand),您必须先以某种方式获取 MainViewModel。

一种方法是使用RelativeSource 进行绑定,找到Window,然后使用DataContext.PausePrinterCommand 作为绑定路径。像这样:

<Button Grid.Column="1" Content="Pause"
        Command="{Binding RelativeSource={RelativeSource Window},
                  Path=DataContext.PausePrinterCommand}" />

【讨论】:

  • +1 用于比我更快、更彻底地输入此内容。 :)
  • 好收获。 ItemsSource={Binding Printers} 是罪魁祸首。
【解决方案2】:

使用元素绑定

<Window x:Class="RET.CMS.Printing.App.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:RET.CMS.Printing.App.ViewModel"
    Height="350" Width="525"
    x:Name="rootWindow"
    WindowStartupLocation="CenterScreen"
    Title="{Binding Path=DisplayName}" >
       .
       .
       .
  <Button Grid.Column="1" Content="Pause" Command="{Binding ElementName=rootWindow, Path=DataContext.PausePrinterCommand}"></Button>

【讨论】:

  • 元素绑定对我来说很关键,但在列表框的情况下,我必须引用列表框而不是页面根目录才能使其工作。但是谢谢,这是唯一对我有用的方法。
【解决方案3】:

数据模板中的按钮应绑定到命令 PauseCommand,因为它的数据上下文是 PrinterViewModel 而不是 MainWindowViewModel。如果您查看调试输出,VS 会清楚地告诉您。

【讨论】:

  • 我发誓我做到了,但它没有用 - 但现在它正在工作。谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-06
  • 1970-01-01
  • 2015-06-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多