从mvvm

时间:2016-08-18 11:34:10

标签: c# wpf mvvm

作为WPF和MVVM的初学者,我有两个问题: 我构建了一个用户控件,它在一个窗口中使用,并包含两个StackPanel。

  1. 在第一个SP中,我有一个ListView,它有一个编辑按钮并绑定到ViewModel。 在选择ListItem之前,将禁用编辑按钮。选择ListItem时,将启用所有编辑按钮。 如何解决这个问题,以便只启用所选ListItem的编辑按钮。 PS。我的编辑按钮是一个自定义控件,只是为了获取图像+文本。
  2. 第二个SP,它将包含所选ListItem的编辑表单,目标是只有在我点击编辑按钮时才能看到编辑表单。
  3. 提前谢谢

    编辑按钮(列)

    <GridViewColumn Header="Edit" Width="auto">
                                             <GridViewColumn.CellTemplate>
                                               <DataTemplate>
    
                                                        <cc:MyEditDeleteButton x:Name="BoolToVisibility" 
                                                                               ImageSource="../Images/Edit.png" 
                                                                               Content="Edit" 
                                                                               Command="{Binding EditCommand}" DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType=ListView}}" 
                                                                               CommandParameter="{Binding Path=SelectedArticle.Id}" 
                                                                               Width="auto"/>
    
                                                </DataTemplate>
                                            </GridViewColumn.CellTemplate>
                                        </GridViewColumn>
    

    第二个StackPanel

    <StackPanel Visibility="{Binding ElementName=BoolToVisibility,Path=IsChecked, Converter={ StaticResource BooleanToVisibilityConverter}}">
                                <Label  Content="blablabla"></Label>
                        </StackPanel>
    

    二手转换器:

    <UserControl.Resources>
        <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
    </UserControl.Resources>
    

    我的自定义控件的类-Edit Button-继承自ToggleButton

     public class MyEditDeleteButton : ToggleButton
    {
        static MyEditDeleteButton()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(MyEditDeleteButton), new FrameworkPropertyMetadata(typeof(MyEditDeleteButton)));
        }
        public ImageSource ImageSource
        {
            get { return (ImageSource)GetValue(ImageSourceProperty); }
            set { SetValue(ImageSourceProperty, value); }
        }
    
        // Using a DependencyProperty as the backing store for ImageSource.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ImageSourceProperty =
            DependencyProperty.Register("ImageSource", typeof(ImageSource), typeof(MyEditDeleteButton), new UIPropertyMetadata(null));
    
    }
    

    所以,2个问题:

    • 选择列表项目时,将在整个列中启用编辑按钮

    • 单击编辑按钮时,显示第二个堆栈面板的可见性。

    更新

    谢谢你的回复。 问题没有完全解决,也许我做错了。 这是我做的:

    @Ed Plunkett。我看不出如何声明_EditItem字段。

    private Item _editItem;
    

    你的意思是来自ViewModel的项目? 在我的视图模型中,我有一个没有参数的构造函数

    Edit item = new Item (item);
    
    <StackPanel>
    <StackPanel>
            ... ListView with the Edit Button
    </StackPanel>
    <StackPanel Visibility="{Binding Mode=OneWay, Source={StaticResource StackCollapsed}}">                        
           <Label  Content="blablabla"></Label>
     </StackPanel>
     </StackPanel>
    

    在App.xaml中:

    <Application.Resources>
            <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
    
            <Style x:Key="StackCollapsed" TargetType="StackPanel">
                <Setter Property="Visibility" Value="Collapsed"/>
                <Style.Triggers>
                    <DataTrigger Binding="{Binding Path=(viewModels:ArticleViewModel.IsEditable), Converter={ StaticResource BooleanToVisibilityConverter}}" Value="{x:Null}">
                        <Setter Property="Visibility" Value="Visible"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
     </Application.Resources>
    

    我仍然看到StackPanel,它的可见性从未改变过。

1 个答案:

答案 0 :(得分:0)

以下是我将如何做到这一点。

首先,为ViewModel提供一个带有EditItem setter的protected属性。它的类型是你的项目类型。当EditItem为空时,隐藏编辑器区域。

<StackPanel.Style>
    <Style TargetType="StackPanel">
        <Style.Triggers>
            <DataTrigger Binding="{Binding EditItem}" Value="{x:Null}">
                <Setter Property="Visibility" Value="Collapsed" />
            </DataTrigger>
        </Style.Triggers>
    </Style>
</StackPanel.Style>

我的EditItemCommand在XAML中看起来和你的很相似:

<GridViewColumn.CellTemplate>
    <DataTemplate>
        <Button
            Content="Edit"
            Command="{Binding DataContext.EditItemCommand, RelativeSource={RelativeSource AncestorType=ListView}}"
            CommandParameter="{Binding}"
            IsEnabled="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=ListViewItem}}"
            />
    </DataTemplate>
</GridViewColumn.CellTemplate>

...但是在viewmodel中,它会将EditItem设置为命令参数的克隆,并将命令参数存储在私有字段Item _editItemOriginal中。

我不同意您决定仅为所选行启用“编辑”按钮。我让用户直接进入编辑按钮而不先点击该行。但这是你的电话,上面IsEnabled中的CellTemplate绑定说明了实现这一目标的简单方法。

我的SaveEditItemCommand会使用其命令参数_editItemOriginal的任何已编辑属性更新Item。只有当CanExecute参数的参数为​​Item时,它的CancelEditCommand代码才会返回true。

我的EditItem会将_editItemOriginalnull设置为CanExecute。同样,仅当Item代码的参数为DelegateCommand时,它才会返回true。

对于所有这些命令,我​​会使用CanExecuteChanged类来让我明确地提出EditItem。我的#region EditItem Property private Item _editItem = null; public Item EditItem { get { return _editItem; } protected set { if (value != _editItem) { _editItem = value; if (_editItem == null) { _editItemOriginal = null; } OnPropertyChanged(); EditItemCommand.RaiseCanExecuteChanged(); SaveItemCommand.RaiseCanExecuteChanged(); CancelEditCommand.RaiseCanExecuteChanged(); } } } private Item _editItemOriginal; protected void EditThisItem(Item item) { EditItem = new Item(item); _editItemOriginal = item; } #endregion EditItem Property 制定者将负责:

"coordinates":{"0":{"received_at":1471529314,"lat":28.6888798,"long":77.3247225}}