我已经看到了其他问题,但是从来没有任何明确的代码来描述修复。我无法在我的ItemTemplate中获得一个按钮以在任何地方绑定到任何命令。很沮丧。我是一个完整的MVVM新手,顺便说一句。
这是我的Window 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;
}
}
}
请帮忙!为什么我不能得到这个?
答案 0 :(得分:8)
ItemTemplate中Button的 DataContext
是一个PrinterViewModel对象(具有PauseCommand
)。但是,您正在尝试将PausePrinterCommand
绑定到它,这是MainWindowViewModel的属性。
为了使这项工作(即使用ItemTemplate中的Button执行MainViewModel.PausePrinterCommand),你必须先以某种方式获得MainViewModel。
执行此操作的一种方法是使用RelativeSource进行绑定,找到Window,并使用DataContext.PausePrinterCommand作为绑定路径。像这样:
<Button Grid.Column="1" Content="Pause"
Command="{Binding RelativeSource={RelativeSource Window},
Path=DataContext.PausePrinterCommand}" />
答案 1 :(得分:3)
使用元素绑定
<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>
答案 2 :(得分:2)
datatemplate中的按钮应绑定到命令PauseCommand,因为它的datacontext是PrinterViewModel而不是MainWindowViewModel。如果查看调试输出,VS会清楚地告诉你。