我正在使用WPF建立一个销售点系统,我遇到了一堵砖墙。
因此,我尝试实现的其中一个组件是“项目面板”(Canvas),它承载“项目按钮”(按钮)。此面板用于添加表示系统中使用的项目的按钮。您可以锁定/解锁面板,以便将新创建的按钮移动到用户喜欢的位置。
我想在Item Buttons上有一个依赖属性,指示按钮是否被锁定(或不是)。创建/锁定/解锁项目按钮是通过使用项目面板中的上下文菜单完成的。
下面我已经包含了我的代码:
ItemPanel.xaml
<Window x:Class="ItemPanel.Views.ItemPanelView"
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:ItemPanel"
xmlns:viewModels="clr-namespace:ItemPanel.ViewModels"
xmlns:views="clr-namespace:ItemPanel.Views"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=viewModels:ItemPanelViewModel, IsDesignTimeCreatable=True}"
Title="ItemPanelView"
Height="800" Width="800">
<ItemsControl ItemsSource="{Binding ItemButtons}">
<!--ItemPanel-->
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas x:Name="ItemPanel"
Background="LightGray"
ClipToBounds="True"
Focusable="False"
Width="400"
Height="400">
<Canvas.ContextMenu>
<ContextMenu>
<MenuItem Header="Add Item"
Command="{Binding CreateItemButtonCommand}"/>
<MenuItem Header="Lock Panel"
IsCheckable="True"
IsChecked="{Binding IsLocked}"
Command="{Binding LockItemPanelCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource Self}, Path=IsChecked}"/>
</ContextMenu>
</Canvas.ContextMenu>
</Canvas>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<!--ItemButton-->
<ItemsControl.ItemTemplate>
<DataTemplate>
<views:ItemButtonView x:Name="ItemButton" Lock="{Binding DataContext.IsLocked, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
ItemPanelView.xaml.cs
namespace ItemPanel.Views
{
/// <summary>
/// Interaction logic for ItemPanelView.xaml
/// </summary>
public partial class ItemPanelView : Window
{
public ItemPanelView()
{
InitializeComponent();
DataContext = new ItemPanelViewModel();
}
}
}
ItemPanelViewModel.cs
namespace ItemPanel.ViewModels
{
public class ItemPanelViewModel : ViewModelBase
{
private bool _isLocked;
public ItemPanelViewModel()
{
IsLocked = true;
ItemButtons = new ObservableCollection<ItemButtonViewModel>();
CreateItemButtonCommand = new DelegateCommand(CreateItemButtonCommandHandler);
LockItemPanelCommand = new DelegateCommand<bool?>(LockItemPanelCommandHandler);
}
public ObservableCollection<ItemButtonViewModel> ItemButtons { get; private set; }
#region Create ItemButton
public DelegateCommand CreateItemButtonCommand { get; private set; }
private void CreateItemButtonCommandHandler()
{
//ItemButtonViewModel viewModel = _container.Resolve<ItemButtonViewModel>();
ItemButtonViewModel viewModel = new ItemButtonViewModel() { Label = Guid.NewGuid()};
ItemButtons.Add(viewModel);
}
#endregion
#region Lock ItemPanel
public bool IsLocked
{
get
{
return _isLocked;
}
set
{
_isLocked = value;
OnPropertyChanged("IsLocked");
}
}
public DelegateCommand<bool?> LockItemPanelCommand { get; private set; }
public void LockItemPanelCommandHandler(bool? isChecked)
{
//if (!isChecked.HasValue)
// return;
//foreach (ItemButtonViewModel itemButton in ItemButtons)
//{
//itemButton.IsLocked = IsLocked;
//}
}
#endregion
}
}
ItemButtonView.xaml
<Button x:Class="ItemPanel.Views.ItemButtonView"
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:ItemPanel.Views"
xmlns:viewModels="clr-namespace:ItemPanel.ViewModels"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=viewModels:ItemButtonViewModel, IsDesignTimeCreatable=True}"
Width="100" Height="100"
Content="{Binding Label}"
ToolTip="{Binding Label}">
</Button>
ItemButtonView.xaml.cs
namespace ItemPanel.Views
{
/// <summary>
/// Interaction logic for ItemButtonView.xaml
/// </summary>
public partial class ItemButtonView : Button
{
public ItemButtonView()
{
InitializeComponent();
}
public static readonly DependencyProperty LockProperty =
DependencyProperty.Register("Lock", typeof(bool), typeof(ItemButtonView));
public bool Lock
{
get { return (bool)GetValue(LockProperty); }
set { SetValue(LockProperty, value); }
}
}
}
ItemButtonViewModel.cs
namespace ItemPanel.ViewModels
{
public class ItemButtonViewModel : ViewModelBase
{
public Guid Label { get; set; }
}
}
所以我的问题是,为什么ItemButton视图中的Lock依赖属性没有被ItemPanel IsLocked属性更新。
从我的理解是它应该受到约束......但似乎没有任何东西得到更新。
我真的很感激任何帮助。
由于
答案 0 :(得分:0)
我在这个例子中使用MVVM Light。
所以你有
<强> XAML 强>
<Window x:Class="WpfApplication6.MainWindow"
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:WpfApplication6"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
mc:Ignorable="d" d:DataContext="{d:DesignInstance local:MyModel}"
Title="MainWindow" Height="350" Width="525" x:Name="Window">
<Window.Resources>
<local:MyTemplateSelector x:Key="MyTemplateSelector" />
<DataTemplate x:Key="SimpleContentTemplate" DataType="local:SimpleContent">
<Grid Width="200" Height="200" Background="DeepSkyBlue">
<TextBlock Text="{Binding Text}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</DataTemplate>
</Window.Resources>
<Grid>
<ItemsControl ItemsSource="{Binding Elements}" >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas x:Name="Canvas1" IsItemsHost="True" Background="LightBlue">
<Canvas.ContextMenu>
<ContextMenu>
<MenuItem Header="Add button" Command="{Binding AddButton}" IsEnabled="{Binding IsUnlocked}" />
<MenuItem Header="Lock" IsChecked="{Binding IsLocked}" Command="{Binding Lock}" />
</ContextMenu>
</Canvas.ContextMenu>
</Canvas>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate >
<ContentControl Content="{Binding}" ContentTemplateSelector="{StaticResource MyTemplateSelector}">
<i:Interaction.Behaviors>
<local:MovableBehavior Canvas="{Binding ElementName=Canvas1}" CanMove="{Binding ElementName=Window, Path=DataContext.IsUnlocked }"/>
</i:Interaction.Behaviors>
</ContentControl>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</Window>
代码(C#6)
using System;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interactivity;
using System.Windows.Media;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.CommandWpf;
namespace WpfApplication6
{
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
DataContext = new MyModel();
}
}
public class MyModel : ViewModelBase
{
private bool _isLocked;
public MyModel()
{
Lock = new RelayCommand(() =>
{
IsLocked = !IsLocked;
RaisePropertyChanged(() => IsLocked);
});
AddButton = new RelayCommand(() => { Elements.Add(new SimpleContent {Text = "Text"}); });
Elements = new ObservableCollection<object>();
}
public ObservableCollection<object> Elements { get; }
public RelayCommand Lock { get; }
public RelayCommand AddButton { get; }
public bool IsUnlocked => !IsLocked;
public bool IsLocked
{
get { return _isLocked; }
set
{
Set(ref _isLocked, value);
RaisePropertyChanged(() => IsUnlocked);
}
}
}
public class SimpleContent
{
public string Text { get; set; }
}
public class MovableBehavior : Behavior<UIElement>
{
public static readonly DependencyProperty CanvasProperty = DependencyProperty.Register(
"Canvas", typeof(Canvas), typeof(MovableBehavior), new PropertyMetadata(default(Canvas)));
public static readonly DependencyProperty CanMoveProperty = DependencyProperty.Register(
"CanMove", typeof(bool), typeof(MovableBehavior), new PropertyMetadata(default(bool)));
private bool _isDragging;
private Point _point;
public Canvas Canvas
{
get { return (Canvas) GetValue(CanvasProperty); }
set { SetValue(CanvasProperty, value); }
}
public bool CanMove
{
get { return (bool) GetValue(CanMoveProperty); }
set { SetValue(CanMoveProperty, value); }
}
protected override void OnAttached()
{
AssociatedObject.MouseLeftButtonDown += AssociatedObject_MouseLeftButtonDown;
AssociatedObject.MouseLeftButtonUp += AssociatedObject_MouseLeftButtonUp;
AssociatedObject.MouseMove += AssociatedObject_MouseMove;
}
private void AssociatedObject_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
_isDragging = true;
_point = e.GetPosition(AssociatedObject);
AssociatedObject.CaptureMouse();
}
private void AssociatedObject_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
_isDragging = false;
_point = default(Point);
AssociatedObject.ReleaseMouseCapture();
}
private void AssociatedObject_MouseMove(object sender, MouseEventArgs e)
{
if (!_isDragging || !CanMove)
return;
var position = e.GetPosition(Canvas) - _point;
var parent = VisualTreeHelper.GetParent(AssociatedObject) as ContentPresenter;
if (parent == null) throw new ArgumentNullException(nameof(parent));
Canvas.SetLeft(parent, position.X);
Canvas.SetTop(parent, position.Y);
}
}
public class MyTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
var element = container as FrameworkElement;
if (element != null)
{
if (item is SimpleContent)
{
return element.FindResource("SimpleContentTemplate") as DataTemplate;
}
}
return null;
}
}
}
你有很多材料可以让你忙碌,我鼓励你看一下我用过的类型的文档!