如何在列表框+画布中启用自定义形状的大小调整

时间:2014-07-22 22:49:50

标签: c# wpf xaml mvvm resize

基于该问题答案的项目:

Graph nodes coordinates evaluation

并使用MVVM Light Toolkit我正在尝试开发一个应用程序,它不仅允许用户在画布周围移动项目,还可以调整它们的大小。以下是我到目前为止的情况:

http://screenshooter.net/4766406/tfcqpjw

主窗口XAML

<Window x:Class="WpfApplication2.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfApplication2"
    xmlns:localvm="clr-namespace:WpfApplication2.ViewModel"
    Title="MainWindow" Height="350" Width="927.985" x:Name="view">
<Window.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="EditorStyles.xaml"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Window.Resources>
<DockPanel>
    <StackPanel Width="95" DockPanel.Dock="Left" Margin="5,0,0,0">
        <local:ButtonsPanel/>
    </StackPanel>
    <Grid Margin="10">
        <Grid.Resources>
            <BooleanToVisibilityConverter x:Key="BoolToVisibilityConverter"/>
            <CompositeCollection x:Key="Col">
                <CollectionContainer Collection="{Binding DataContext.Notes,Source={x:Reference view}}"/>
            </CompositeCollection>
            <DataTemplate DataType="{x:Type localvm:NoteViewModel}">
                <Grid>
                    <Thumb DragDelta="Thumb_Drag"
                       IsEnabled="{Binding IsSelected,RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}">
                        <Thumb.Template>
                            <ControlTemplate TargetType="Thumb">
                                <Canvas>
                                    <Path Fill="#FFAA0000" Data="{Binding ShapeGeometry}" Stretch="Fill" x:Name="Path"/>
                                </Canvas>
                                <ControlTemplate.Triggers>
                                    <DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}" Value="True">
                                        <Setter TargetName="Path" Property="Fill" Value="Red"/>
                                    </DataTrigger>
                                    <Trigger Property="IsDragging" Value="True">
                                        <Setter TargetName="Path" Property="Fill" Value="Green"/>
                                    </Trigger>
                                </ControlTemplate.Triggers>
                            </ControlTemplate>
                        </Thumb.Template>
                    </Thumb>                        
                </Grid>                    
            </DataTemplate>
        </Grid.Resources>

        <ListBox SelectedItem="{Binding SelectedNote}" 
                 PreviewMouseMove="ListBox_PreviewMouseMove"
                 PreviewMouseDown="ListBox_PreviewMouseDown">
            <ListBox.Template ... > <!-- Collapsed -->
            </ListBox.Template>
            <ListBox.ItemsSource>
                <StaticResource ResourceKey="Col"/>
            </ListBox.ItemsSource>
            <ListBox.ItemsPanel ...> <!-- Collapsed -->
            </ListBox.ItemsPanel>
            <ListBox.ItemContainerStyle>
                <Style TargetType="ListBoxItem">
                    <!-- Moves the object -->
                    <Setter Property="Canvas.Left" Value="{Binding X}"/>
                    <Setter Property="Canvas.Top" Value="{Binding Y}"/>
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="ListBoxItem">
                                <ContentPresenter x:Name="Content"/>                                    
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </ListBox.ItemContainerStyle>
        </ListBox>
    </Grid>
</DockPanel>

Thumb的DragDelta来自MainWindow代码后面的+构造函数:

public MainWindow()
    {
        InitializeComponent();
        DataContext = new MainViewModel();
    }

    private void Thumb_Drag(object sender, DragDeltaEventArgs e)
    {
        var thumb = sender as Thumb;
        if (thumb == null)
            return;

        var note = thumb.DataContext as NoteViewModel;
        if (note == null)
            return;

        note.X += e.HorizontalChange;
        note.Y += e.VerticalChange;
    }

MainViewModel中的重要属性和方法:

public class MainViewModel : ViewModelBase
{
    private ObservableCollection<NoteViewModel> _notes;
    public ObservableCollection<NoteViewModel> Notes
    {
        get { return _notes ?? (_notes = new ObservableCollection<NoteViewModel>()); }
    }

    private NoteViewModel _selectedNote;
    public NoteViewModel SelectedNote {...}

    public MainViewModel()
    {
        _notes = new ObservableCollection<NoteViewModel>(NotesDataSource.GetRandomNotes());
    }

    #region Creating New Notes

    private bool _creatingNewNote;
    public bool CreatingNewNote
    {
        get { return _creatingNewNote; }
        set
        {
            _creatingNewNote = value;
            RaisePropertyChanged("CreatingNewNote");

            if (value)
                CreateNewNote();
            else
                RemoveNewObjects();
        }
    }

    public void CreateNewNote()
    {
        var newnote = new NoteViewModel()
        {
            Name = "Note" + (Notes.Count + 1),
            IsNew = true
        };

        Notes.Add(newnote);
        SelectedNote = newnote;
    }

    public void RemoveNewObjects()
    {
        Notes.Where(x => x.IsNew).ToList().ForEach(x => Notes.Remove(x));
    }
    #endregion
}

NoteViewModel:

public class NoteViewModel : ViewModelBase
{        
    private string _name;
    public string Name
    {
        get { return _name; }
        set
        {
            _name = value;
            RaisePropertyChanged("Name");
        }
    }

    #region Coordinates & Size
    private double _x;
    public double X { ...}

    private double _y;
    public double Y {...}

    private double _width;
    public double Width {...}

    private double _height;
    public double Height {...}
    #endregion

    #region Shape Geometry
    private string _shapeGeometry;
    public string ShapeGeometry {...}
    #endregion

    #region Selection Properties
    private bool _isNew;
    public bool IsNew {...}
    #endregion

    public NoteViewModel()
    {      
        Random random = new Random();
        var notenumber = random.Next(0, 100);
        var notename = "Note" + notenumber;            
        Name = notename;
        X = 10;
        Y = 10;
        ShapeGeometry = "M39.967 23.133c-0.211 0.189-0.523 0.199-0.748 0.028l-7.443-5.664l-3.526 21.095c-0.013 0.08-0.042 0.153-0.083 0.219  c-0.707 3.024-4.566 5.278-9.104 5.278c-5.087 0-9.226-2.817-9.226-6.28s4.138-6.281 9.226-6.281c2.089 0 4.075 0.466 5.689 1.324  l4.664-26.453c0.042-0.242 0.231-0.434 0.475-0.479c0.237-0.041 0.485 0.068 0.611 0.28l9.581 16.192  C40.227 22.637 40.178 22.945 39.967 23.133z";
        Width = CalculateSize("w");
        Height = CalculateSize("h");
    }

    private double CalculateSize(string s) {...}

Thumb允许移动,我试图将上面的例子与这里的例子结合起来(没有Adorners,他们看起来非常复杂,就像我找到的所有其他例子一样):http://www.codeproject.com/Articles/22952/WPF-Diagram-Designer-Part

然而,经过相当长时间的绞尽脑汁之后,我无法找到可行的解决方案。如何调整项目大小?请帮助一位遇险的少女!

0 个答案:

没有答案