我有一个Parent ViewModel,绑定到Parent Window。在里面,有一个ItemsControl,它绑定到Child ViewModels的集合。 ItemsControl创建UserControls(子视图),将其DataContext作为ChildViewModel(根据ItemsControl的工作原理自动生成)。
值得注意的是,我使用Castle Windsor作为IoC。 我也尝试通过(当前正在工作)抽象工厂解析子ViewModels,但它没有帮助。我甚至尝试将子ViewModel注册为单身,但仍然 - 在集合中找不到。
所以我把问题问题简化为简单的类实例化。
现在,我想要的是:
每个提醒(UserControl)都有一个Button,代表关闭。 此按钮绑定到父ViewModel,如下所示:
CloseCommand="{Binding ElementName=level1Listener, Path=DataContext.ReminderBoxCloseCommand}"
其中level1Listener
是ItemsControl
的名称。
到目前为止一切正常,UserControls已创建且所有绑定都有效。但是:
单击“关闭”按钮时,即使绑定命令执行,也不会从集合中删除ViewModel。看来,任何UserControls返回的
ReminderBoxViewModel
实例都不存在于集合中 - 但是UserControl甚至出现直接依赖于它们的存在。当我只是删除某个索引处的元素时 - 一切正常。
UC如何能够返回与“数据上下文”不同的东西?
这怎么可能,或者我完全错过了什么?
这是我的PhoneWindow视图:
<Window x:Class="NoContact.Views.PhoneWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:NoContact.Views"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:avalon="http://icsharpcode.net/sharpdevelop/avalonedit"
xmlns:usercontrols="clr-namespace:NoContact.UserControls"
xmlns:viewModels="clr-namespace:NoContact.ViewModels"
mc:Ignorable="d"
Title="PhoneWindow" Height="600" Width="980"
Background="#22282a">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="600" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Border Grid.Column="0" Margin="10, 10" Style="{StaticResource phoneWindowBorderStyle}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="80"/>
<RowDefinition Height="180" />
<RowDefinition Height="*" />
<RowDefinition Height="100"/>
</Grid.RowDefinitions>
<Border Grid.Row="0" Margin="-1,-1" Style="{StaticResource phoneWindowBorderStyle}">
<StackPanel Orientation="Horizontal">
<Image Margin="15">
<Image.Source>
<DrawingImage>
<DrawingImage.Drawing>
<DrawingGroup>
<GeometryDrawing Brush="#ffcd22"
Geometry="{StaticResource phoneIconGeometry}" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
</Image>
<TextBlock VerticalAlignment="Center" FontSize="30" Style="{StaticResource phoneWindowTextBlockStyle}">Telefon</TextBlock>
</StackPanel>
</Border>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid Grid.Column="0">
<DockPanel LastChildFill="False">
<DockPanel LastChildFill="True" Margin="10,20,0,0" DockPanel.Dock="Top">
<TextBlock Style="{StaticResource phoneWindowTextBlockStyle}">Imię:</TextBlock>
<TextBox Height="30" Margin="46,0,10,0" Style="{StaticResource phoneWindowTextBoxStyle}"></TextBox>
</DockPanel>
<DockPanel LastChildFill="True" Margin="10,20,0,0" DockPanel.Dock="Top">
<TextBlock Style="{StaticResource phoneWindowTextBlockStyle}">Nazwisko:</TextBlock>
<TextBox Height="30" Margin="10,0,10,0" Style="{StaticResource phoneWindowTextBoxStyle}"></TextBox>
</DockPanel>
<DockPanel LastChildFill="True" Margin="10,20,0,0" DockPanel.Dock="top">
<TextBlock Style="{StaticResource phoneWindowTextBlockStyle}">Data:</TextBlock>
<usercontrols:DateTimePicker Height="30" Margin="40,0,10,0" BorderBrush="#ffcd22" BorderThickness="1" Background="#15151a" Foreground="#ffcd22"/>
</DockPanel>
</DockPanel>
</Grid>
<Grid Grid.Column="1">
<DockPanel LastChildFill="False">
<DockPanel LastChildFill="True" Margin="10,20,0,0" DockPanel.Dock="Top">
<TextBlock Style="{StaticResource phoneWindowTextBlockStyle}">Email:</TextBlock>
<TextBox Height="30" Margin="26,0,10,0" Style="{StaticResource phoneWindowTextBoxStyle}"></TextBox>
</DockPanel>
<DockPanel LastChildFill="True" Margin="10,20,0,0" DockPanel.Dock="Top">
<TextBlock Style="{StaticResource phoneWindowTextBlockStyle}">Telefon:</TextBlock>
<TextBox Height="30" Margin="10,0,10,0" Style="{StaticResource phoneWindowTextBoxStyle}"></TextBox>
</DockPanel>
<DockPanel LastChildFill="True" Margin="10,20,0,0" DockPanel.Dock="top">
<TextBlock Style="{StaticResource phoneWindowTextBlockStyle}">Nr. Zamówienia:</TextBlock>
<TextBox Height="30" Margin="10,0,10,0" Style="{StaticResource phoneWindowTextBoxStyle}"></TextBox>
</DockPanel>
</DockPanel>
</Grid>
</Grid>
<Grid Grid.Row="2">
<avalon:TextEditor Margin="10,10" Style="{StaticResource phoneWindowAvalonEditStyle}" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden" WordWrap="True">
</avalon:TextEditor>
</Grid>
<Border Grid.Row="3" Margin="-1,0,-1,-1" Style="{StaticResource phoneWindowBorderStyle}">
<Grid>
<Button Width="170" HorizontalAlignment="Right" Margin="10" Style="{StaticResource flatButtonStyle}">Gotowe</Button>
<Button Width="170" HorizontalAlignment="Left" Margin="10" Style="{StaticResource flatButtonStyle}">Anuluj</Button>
</Grid>
</Border>
</Grid>
</Border>
<Border Grid.Column="1" Margin="10,10" Style="{StaticResource phoneWindowBorderStyle}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="80" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Border Grid.Row="0" Margin="-1,-1,-1,-1" Style="{StaticResource phoneWindowBorderStyle}">
<usercontrols:ImageButton x:Name="addButton" Style="{StaticResource addImageButtonUCStyle}" Text="Dodaj Termin" ClickCommand="{Binding Path=AddReminderCommand}">
</usercontrols:ImageButton>
</Border>
<Border Grid.Row="1" Margin="-1,0,-1,-1" Style="{StaticResource phoneWindowBorderStyle}">
<ScrollViewer VerticalScrollBarVisibility="Hidden" HorizontalScrollBarVisibility="Hidden" Background="#15151a">
<ItemsControl x:Name="level1Listener" ItemsSource="{Binding Path=Reminders, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type viewModels:ReminderBoxViewModel}">
<StackPanel>
<usercontrols:ReminderBox VerticalAlignment="Top" Background="#22282a" Foreground="#ffcd22" Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType={x:Type ScrollViewer}}, Path=ActualWidth}" Height="140" CloseCommand="{Binding ElementName=level1Listener, Path=DataContext.ReminderBoxCloseCommand}"
CommandParameter="{Binding}"/>
<Rectangle Height="1" Margin="10,0" Fill="#ffcd22" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Border>
</Grid>
</Border>
</Grid>
PhoneWindow(查看)代码背后:
namespace NoContact.Views
{
/// <summary>
/// Interaction logic for phoneWindow.xaml
/// </summary>
public partial class PhoneWindow : Window, IView
{
public IViewModel ViewModel { get; private set; }
private IWindowManager _windowManager;
public PhoneWindow(IViewFactory context, IWindowManager windowManager)
{
InitializeComponent();
_windowManager = windowManager;
var obj = context.Create<IPhoneWindowViewModel>();
ViewModel = obj;
this.DataContext = obj;
context.Release(obj);
}
protected override void OnClosed(EventArgs e)
{
_windowManager.RemoveFromWindowList(this);
base.OnClosed(e);
}
}
}
这是MainViewModel:
public class PhoneWindowViewModel : BindableBase, IPhoneWindowViewModel
{
private IWindowManager _windowManager;
private ObservableCollection<IReminderBoxViewModel> _reminders;
public PhoneWindowViewModel(IWindowManager windowManager)
{
_windowManager = windowManager;
_reminders = new ObservableCollection<IReminderBoxViewModel>();
}
public ICommand ReminderBoxCloseCommand { get { return new RelayCommand<ReminderBoxViewModel>(CloseReminderBox); } }
public ICommand AddReminderCommand { get { return new RelayCommand(AddReminder, () => true); } }
public ObservableCollection<IReminderBoxViewModel> Reminders
{
get { return _reminders; }
set
{
_reminders = value;
OnPropertyChanged();
}
}
/// <summary>
/// Delegates closing the window, associated with
/// this ViewModel instance.
/// </summary>
private void CloseWindow()
{
_windowManager.CloseWindow(this);
}
/// <summary>
/// "Closes" the Reminder Box by deleting it from the Collection
/// </summary>
private void CloseReminderBox(ReminderBoxViewModel viewModel)
{
Reminders.Remove(viewModel);
var index = Reminders.IndexOf(viewModel);
System.Windows.MessageBox.Show(index.ToString());
}
/// <summary>
/// Adds the reminder to the Collection
/// </summary>
private void AddReminder()
{
Reminders.Add(new ReminderViewModel());
}
最后,我的userControl代码:
namespace NoContact.UserControls
{
/// <summary>
/// Interaction logic for ReminderBox.xaml
/// </summary>
public partial class ReminderBox : UserControl
{
#region Dependency Properties
public Brush CloseButtonBrush
{
get { return (Brush)GetValue(CloseButtonBrushProperty); }
set { SetValue(CloseButtonBrushProperty, value); }
}
public new Brush Background
{
get { return (Brush)GetValue(BackgroundProperty); }
set { SetValue(BackgroundProperty, value); }
}
public new Brush Foreground
{
get { return (Brush)GetValue(ForegroundProperty); }
set { SetValue(ForegroundProperty, value); }
}
public ICommand CloseCommand
{
get { return (ICommand)GetValue(CloseCommandProperty); }
set { SetValue(CloseCommandProperty, value); }
}
public object CommandParameter
{
get { return (object)GetValue(CommandParameterProperty); }
set { SetValue(CommandParameterProperty, value); }
}
public static readonly DependencyProperty CloseButtonBrushProperty =
DependencyProperty.Register("CloseButtonBrush", typeof(Brush), typeof(ReminderBox), new UIPropertyMetadata(null));
public static readonly new DependencyProperty BackgroundProperty =
DependencyProperty.Register("Background", typeof(Brush), typeof(ReminderBox), new UIPropertyMetadata(null));
public static readonly new DependencyProperty ForegroundProperty =
DependencyProperty.Register("Foreground", typeof(Brush), typeof(ReminderBox), new UIPropertyMetadata(null));
public static readonly DependencyProperty CloseCommandProperty =
DependencyProperty.Register("CloseCommand", typeof(ICommand), typeof(ReminderBox), new UIPropertyMetadata(null));
public static readonly DependencyProperty CommandParameterProperty =
DependencyProperty.Register("CommandParameter", typeof(object), typeof(ReminderBox), new UIPropertyMetadata(null));
#endregion
public ReminderBox()
{
InitializeComponent();
}
}
}
提醒XAML:
<UserControl x:Class="NoContact.UserControls.ReminderBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:NoContact.UserControls"
xmlns:usercontrols="clr-namespace:NoContact.UserControls"
xmlns:helpers="clr-namespace:NoContact.Helpers"
mc:Ignorable="d"
x:Name="ReminderBoxUC"
d:DesignHeight="130" d:DesignWidth="400">
<Grid>
<Border Background="{Binding ElementName=ReminderBoxUC, Path=Background}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="0.5*" />
<RowDefinition Height="0.5*" />
<RowDefinition Height="1*" />
</Grid.RowDefinitions>
<Button Grid.Row="0" Width="20" Height="20" Style="{StaticResource flatButtonStyle}" Background="Transparent" Foreground="Transparent"
HorizontalAlignment="Right"
VerticalAlignment="Top"
Margin="0,10,10,0"
Command="{Binding ElementName=ReminderBoxUC, Path=CloseCommand}">
<Border Name="closeButtonBackgroundBorder" CornerRadius="5" Style="{StaticResource CloseButtonReminderBox_BorderUCStyle}">
<Image Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Button}}, Path=ActualWidth}"
Height="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Button}}, Path=ActualHeight}"
HorizontalAlignment="Center" VerticalAlignment="Center">
<Image.Source>
<DrawingImage>
<DrawingImage.Drawing>
<DrawingGroup>
<GeometryDrawing Brush="{Binding ElementName=ReminderBoxUC, Path=CloseButtonBrush}" Geometry="{StaticResource closeIconGeometry}" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
</Image>
</Border>
</Button>
<StackPanel Grid.Row="1" Orientation="Horizontal" Margin="10,0">
<TextBlock Foreground="{Binding ElementName=ReminderBoxUC, Path=Foreground}"
VerticalAlignment="Center" HorizontalAlignment="Left">Przypomnij:
</TextBlock>
<RadioButton Name="RemindOnceRadioButton" IsChecked="True"
Foreground="{Binding ElementName=ReminderBoxUC, Path=Foreground}"
Style="{StaticResource RadioButtonStyle}"
VerticalAlignment="Center" Margin="25,0,0,0">1 Raz</RadioButton>
<RadioButton Name="RemindMultipleRadioButton"
Foreground="{Binding ElementName=ReminderBoxUC, Path=Foreground}"
Style="{StaticResource RadioButtonStyle}"
VerticalAlignment="Center" Margin="25,0,0,0">Wielokrotnie</RadioButton>
</StackPanel>
<DockPanel Grid.Row="2"
Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Grid}}, Path=ActualWidth}">
<usercontrols:DateTimePicker Height="25" Margin="10,0" BorderBrush="#ffcd22" BorderThickness="1" Foreground="#ffcd22" Background="#15151a" Width="150" />
<ComboBox Width="150" Height="25" HorizontalAlignment="Right" Margin="10,0" Style="{StaticResource comboBoxStyle}" ItemsSource="{Binding Source={helpers:EnumBindingSource {x:Type local:TimePeriods}}}"
SelectedIndex="0" />
</DockPanel>
</Grid>
</Border>
</Grid>
<UserControl.Resources>
<Style TargetType="local:ReminderBox">
<Setter Property="CloseButtonBrush" Value="#ffcd22" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=closeButtonBackgroundBorder, Path=IsMouseOver}" Value="True">
<Setter Property="CloseButtonBrush" Value="#22282a" />
</DataTrigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
对于ReminderViewModel,它当前为空,除了来自(当前为空)接口IReminderViewModel的继承。
答案 0 :(得分:1)
您的问题似乎是,您将CommandParameter
DP设置为绑定到当前ReminderBoxViewModel
,但您没有在ReminderBox中的任何位置使用它。
在提醒XAML中,您正确地将Button的Command
绑定到ReminderBox的CloseCommand
,而不是将Button的CommandParameter
设置为CommandParameter
的{{1}}你的ReminderBox。
ReminderBox的XAML的相关代码:
<Button ...
Command="{Binding ElementName=ReminderBoxUC, Path=CloseCommand}"
CommandParameter"{Binding ElementName=ReminderBoxUC, Path=CommandParameter}">
...
</Button>