Отдельный WPF XAML Просмотр кода и логики - PullRequest
0 голосов
/ 07 февраля 2020

Я хочу переместить логи c из файла xaml.cs для дальнейшего повторного использования в других компонентах представления. Я знаю, что я должен реализовать шаблон mvvm для достижения этой цели. Основная проблема, которую я не могу понять, как избавиться от сильной зависимости с помощью пользовательского интерфейса. Например, код, который я хочу переместить в отдельный класс, зависит от таких элементов пользовательского интерфейса, как CanDrawing canvas, PixelsInMillimeterTextBox text box, Image ReferenceImage. Как сделать что-то подобное? Я хочу вырезать это из MainWindow.Xaml.cs:

private Line _selectedLine;

private List<Line> _horizontalLines = new List<Line>();

private List<Line> _verticalLines = new List<Line>();

private bool _twoLineMode = false;

private List<Line> _lines = new List<Line>();

[DllImport("gdi32.dll")]
private static extern bool LineDDA(int nXStart, int nYStart, int nXEnd, int nYEnd, LineDdaProc lpLineFunc, IntPtr lpData);

// The signature for the callback method
private delegate void LineDdaProc(int x, int y, IntPtr lpData);

// The mouse is up. See whether we're over an end point or segment.
private void canDrawing_MouseMove_NotDown(object sender, MouseEventArgs e)
{
    Cursor newCursor = Cursors.Cross;

    // See what we're over.
    Point location = e.MouseDevice.GetPosition(CanDrawing);

    // Set the new cursor.
    if (CanDrawing.Cursor != newCursor)
        CanDrawing.Cursor = newCursor;
}

// See what we're over and start doing whatever is appropriate.
private void canDrawing_MouseDown(object sender, MouseButtonEventArgs e)
{
    // See what we're over.
    Point location = e.MouseDevice.GetPosition(CanDrawing);

    // Start drawing a new segment.
    CanDrawing.MouseMove -= canDrawing_MouseMove_NotDown;
    CanDrawing.MouseMove += canDrawing_MouseMove_Drawing;
    CanDrawing.MouseUp += canDrawing_MouseUp_Drawing;
    CanDrawing.MouseLeave += ReferenceImage_NewSegmentDrawingMouseLeave;
    Application.Current.Deactivated += ReferenceImage_NewSegmentDrawingLostFocus;

    _selectedLine = new Line
    {
        Stroke = Brushes.Yellow,
        X1 = e.GetPosition(ReferenceImage).X,
        Y1 = e.GetPosition(ReferenceImage).Y,
        X2 = e.GetPosition(ReferenceImage).X,
        Y2 = e.GetPosition(ReferenceImage).Y
    };

    CanDrawing.Children.Add(_selectedLine);
}

#region Drawing

// We're drawing a new segment.
private void canDrawing_MouseMove_Drawing(object sender, MouseEventArgs e)
{
    // Update the new line's end point.
    _selectedLine.X2 = e.GetPosition(ReferenceImage).X;
    _selectedLine.Y2 = e.GetPosition(ReferenceImage).Y;
}

// Stop drawing.
private void canDrawing_MouseUp_Drawing(object sender, MouseEventArgs e)
{
    // Reset the event handlers.
    CanDrawing.MouseMove -= canDrawing_MouseMove_Drawing;
    CanDrawing.MouseMove += canDrawing_MouseMove_NotDown;
    CanDrawing.MouseUp -= canDrawing_MouseUp_Drawing;
    CanDrawing.MouseLeave -= ReferenceImage_NewSegmentDrawingMouseLeave;
    Application.Current.Deactivated -= ReferenceImage_NewSegmentDrawingLostFocus;

    // If the new segment has no length, delete it.
    if ((_selectedLine.X1 == _selectedLine.X2) && (_selectedLine.Y1 == _selectedLine.Y2) || _selectedLine == null)
        CanDrawing.Children.Remove(_selectedLine);
    else
    {
        var point11 = new System.Drawing.Point(Convert.ToInt32(_selectedLine.X1), Convert.ToInt32(_selectedLine.Y1));
        var point22 = new System.Drawing.Point(Convert.ToInt32(_selectedLine.X2), Convert.ToInt32(_selectedLine.Y2));

        if (_twoLineMode)
        {
            if (Math.Abs(_selectedLine.X1 - _selectedLine.X2) > Math.Abs(_selectedLine.Y1 - _selectedLine.Y2))
            {
                _selectedLine.Stroke = Brushes.DeepPink;
                if (_horizontalLines.Count > 0)
                {
                    CanDrawing.Children.Remove(_horizontalLines[_horizontalLines.Count - 1]);
                }

                _horizontalLines.Add(_selectedLine);

                PixelsInMillimeterTextBox.Text = GetPointsOnLine(point11, point22).Count.ToString();
            }
            else
            {
                _selectedLine.Stroke = Brushes.Green;
                if (_verticalLines.Count > 0)
                {
                    CanDrawing.Children.Remove(_verticalLines[_verticalLines.Count - 1]);
                }

                _verticalLines.Add(_selectedLine);

                PixelsInMillimeterTextBox.Text = GetPointsOnLine(point11, point22).Count.ToString();
            }

            _lines.Add(_selectedLine);
        }
        else
        {
            _selectedLine.Stroke = Brushes.DeepPink;

            if (_lines.Count > 0)
            {
                CanDrawing.Children.Remove(_lines[_lines.Count - 1]);
            }

            _lines.Add(_selectedLine);

            PixelsInMillimeterTextBox.Text = GetPointsOnLine(point11, point22).Count.ToString();
        }
    }
}

#endregion Drawing

#region "Control Leave Handlers"

private void ReferenceImage_NewSegmentDrawingMouseLeave(object sender, MouseEventArgs e)
{
    if (e.RightButton == MouseButtonState.Pressed)
    {
        canDrawing_MouseUp_Drawing(sender, e);
    }
}

private void ReferenceImage_NewSegmentDrawingLostFocus(object sender, EventArgs e)
{
    if (Mouse.RightButton == MouseButtonState.Pressed)
    {
        canDrawing_MouseUp_Drawing(sender, new MouseEventArgs(Mouse.PrimaryDevice, 0));
    }
}

#endregion

private void DeleteButton_Click(object sender, RoutedEventArgs e)
{
    foreach (var line in _lines)
    {
        CanDrawing.Children.Remove(line);
    }

    _lines.Clear();
}

public static List<Point> GetPointsOnLine(System.Drawing.Point point1, System.Drawing.Point point2)
{
    var points = new List<Point>();
    var handle = GCHandle.Alloc(points);
    try
    {
        LineDDA(point1.X, point1.Y, point2.X, point2.Y, GetPointsOnLineCallback, GCHandle.ToIntPtr(handle));
    }
    finally
    {
        handle.Free();
    }
    return points;
}

private static void GetPointsOnLineCallback(int x, int y, IntPtr lpData)
{
    var handle = GCHandle.FromIntPtr(lpData);
    var points = (List<Point>)handle.Target;
    points.Add(new Point(x, y));
}

У меня есть MainWindow.Xaml.cs:

    namespace DDrop
    {
        /// <summary>
        /// Interaction logic for MainWindow.xaml
        /// </summary>
        public partial class MainWindow : Window
        {
            ObservableCollection<DropPhoto> DropImages = new ObservableCollection<DropPhoto>();
            PythonProvider pythonProvider = new PythonProvider();
            ExcelOperations excelOperations = new ExcelOperations();

            public MainWindow()
            {
                InitializeComponent();
                Photos.ItemsSource = DropImages;
            }

...................................................

            // The line we're drawing or moving.
            private Line _selectedLine;

            private List<Line> _horizontalLines = new List<Line>();

            private List<Line> _verticalLines = new List<Line>();

            private bool _twoLineMode = false;

            private List<Line> _lines = new List<Line>();

            [DllImport("gdi32.dll")]
            private static extern bool LineDDA(int nXStart, int nYStart, int nXEnd, int nYEnd, LineDdaProc lpLineFunc, IntPtr lpData);

            // The signature for the callback method
            private delegate void LineDdaProc(int x, int y, IntPtr lpData);

            // The mouse is up. See whether we're over an end point or segment.
            private void canDrawing_MouseMove_NotDown(object sender, MouseEventArgs e)
            {
                Cursor newCursor = Cursors.Cross;

                // See what we're over.
                Point location = e.MouseDevice.GetPosition(CanDrawing);

                // Set the new cursor.
                if (CanDrawing.Cursor != newCursor)
                    CanDrawing.Cursor = newCursor;
            }

            // See what we're over and start doing whatever is appropriate.
            private void canDrawing_MouseDown(object sender, MouseButtonEventArgs e)
            {
                // See what we're over.
                Point location = e.MouseDevice.GetPosition(CanDrawing);

                // Start drawing a new segment.
                CanDrawing.MouseMove -= canDrawing_MouseMove_NotDown;
                CanDrawing.MouseMove += canDrawing_MouseMove_Drawing;
                CanDrawing.MouseUp += canDrawing_MouseUp_Drawing;
                CanDrawing.MouseLeave += ReferenceImage_NewSegmentDrawingMouseLeave;
                Application.Current.Deactivated += ReferenceImage_NewSegmentDrawingLostFocus;

                _selectedLine = new Line
                {
                    Stroke = Brushes.Yellow,
                    X1 = e.GetPosition(ReferenceImage).X,
                    Y1 = e.GetPosition(ReferenceImage).Y,
                    X2 = e.GetPosition(ReferenceImage).X,
                    Y2 = e.GetPosition(ReferenceImage).Y
                };

                CanDrawing.Children.Add(_selectedLine);
            }

             #region Drawing

            // We're drawing a new segment.
            private void canDrawing_MouseMove_Drawing(object sender, MouseEventArgs e)
            {
                // Update the new line's end point.
                _selectedLine.X2 = e.GetPosition(ReferenceImage).X;
                _selectedLine.Y2 = e.GetPosition(ReferenceImage).Y;
            }

            // Stop drawing.
            private void canDrawing_MouseUp_Drawing(object sender, MouseEventArgs e)
            {            
                // Reset the event handlers.
                CanDrawing.MouseMove -= canDrawing_MouseMove_Drawing;
                CanDrawing.MouseMove += canDrawing_MouseMove_NotDown;
                CanDrawing.MouseUp -= canDrawing_MouseUp_Drawing;
                CanDrawing.MouseLeave -= ReferenceImage_NewSegmentDrawingMouseLeave;
                Application.Current.Deactivated -= ReferenceImage_NewSegmentDrawingLostFocus;

                // If the new segment has no length, delete it.
                if ((_selectedLine.X1 == _selectedLine.X2) && (_selectedLine.Y1 == _selectedLine.Y2) || _selectedLine == null) 
                    CanDrawing.Children.Remove(_selectedLine);
                else
                {
                    var point11 = new System.Drawing.Point(Convert.ToInt32(_selectedLine.X1), Convert.ToInt32(_selectedLine.Y1));
                    var point22 = new System.Drawing.Point(Convert.ToInt32(_selectedLine.X2), Convert.ToInt32(_selectedLine.Y2));

                    if (_twoLineMode)
                    {
                        if (Math.Abs(_selectedLine.X1 - _selectedLine.X2) > Math.Abs(_selectedLine.Y1 - _selectedLine.Y2))
                        {
                            _selectedLine.Stroke = Brushes.DeepPink;
                            if (_horizontalLines.Count > 0)
                            {
                                CanDrawing.Children.Remove(_horizontalLines[_horizontalLines.Count - 1]);
                            }

                            _horizontalLines.Add(_selectedLine);

                            PixelsInMillimeterTextBox.Text = GetPointsOnLine(point11, point22).Count.ToString();
                        }
                        else
                        {
                            _selectedLine.Stroke = Brushes.Green;
                            if (_verticalLines.Count > 0)
                            {
                                CanDrawing.Children.Remove(_verticalLines[_verticalLines.Count - 1]);
                            }

                            _verticalLines.Add(_selectedLine);

                            PixelsInMillimeterTextBox.Text = GetPointsOnLine(point11, point22).Count.ToString();
                        }

                        _lines.Add(_selectedLine);
                    }
                    else
                    {
                        _selectedLine.Stroke = Brushes.DeepPink;

                        if (_lines.Count > 0)
                        {
                            CanDrawing.Children.Remove(_lines[_lines.Count - 1]);
                        }

                        _lines.Add(_selectedLine);

                        PixelsInMillimeterTextBox.Text = GetPointsOnLine(point11, point22).Count.ToString();
                    }
                }
            }

            #endregion Drawing

            #region "Control Leave Handlers"

            private void ReferenceImage_NewSegmentDrawingMouseLeave(object sender, MouseEventArgs e)
            {
                if (e.RightButton == MouseButtonState.Pressed)
                {
                    canDrawing_MouseUp_Drawing(sender, e);
                }
            }

            private void ReferenceImage_NewSegmentDrawingLostFocus(object sender, EventArgs e)
            {
                if (Mouse.RightButton == MouseButtonState.Pressed)
                {
                    canDrawing_MouseUp_Drawing(sender, new MouseEventArgs(Mouse.PrimaryDevice, 0));
                }
            }

            #endregion

            private void DeleteButton_Click(object sender, RoutedEventArgs e)
            {
                foreach (var line in _lines)
                {
                    CanDrawing.Children.Remove(line);
                }

                _lines.Clear();
            }

            public static List<Point> GetPointsOnLine(System.Drawing.Point point1, System.Drawing.Point point2)
            {
                var points = new List<Point>();
                var handle = GCHandle.Alloc(points);
                try
                {
                    LineDDA(point1.X, point1.Y, point2.X, point2.Y, GetPointsOnLineCallback, GCHandle.ToIntPtr(handle));
                }
                finally
                {
                    handle.Free();
                }
                return points;
            }

            private static void GetPointsOnLineCallback(int x, int y, IntPtr lpData)
            {
                var handle = GCHandle.FromIntPtr(lpData);
                var points = (List<Point>)handle.Target;
                points.Add(new Point(x, y));
            }

................................................
        }

и соответствующий XAML:

<Window x:Class="DDrop.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:utility="clr-namespace:DDrop.Utility"
        xmlns:cc="clr-namespace:SimpuControls;assembly=SimpuControls"
        mc:Ignorable="d"
        Title="DDrop" Height="629" Width="800" Icon="Resources/Icons/MainIcon.png" WindowState="Maximized">
    <Grid>
        <TabControl Margin="10,37,10,47">
            <TabItem Header="Менеджер Серий">
                <Grid>
                    <cc:SimpuDataGrid EnableFullTextSearch="True" Margin="10">
                        <DataGrid.Columns>
                            <DataGridTextColumn Header="ID" Binding="{Binding ID}"/>
                            <DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
                            <DataGridTextColumn Header="Email" Binding="{Binding Email}"/>
                        </DataGrid.Columns>
                    </cc:SimpuDataGrid>
                </Grid>
            </TabItem>
            <TabItem Header="Серия">
                <TabControl Margin="10,3,10,5">
                    <TabItem Header="Фотографии">
                        <Grid Background="#FFE5E5E5" RenderTransformOrigin="0.56,0.503">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="*" />
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="*" />
                            </Grid.RowDefinitions>
                            <Border Background="Gainsboro" BorderThickness="1" Height="28" Margin="10,10,10,0" VerticalAlignment="Top">
                                <Grid>
                                    <Button Grid.Row="0" Name="AddPhotoButton"  HorizontalAlignment="Left" Margin="0,0,0,-2" VerticalAlignment="Top" Width="28" BorderBrush="{x:Null}" Background="{x:Null}" Height="25" Click="MenuItemChoosePhotos_OnClick">
                                        <ContentControl Content="{StaticResource AddIcon}" Height="20"/>
                                    </Button>
                                    <Button Grid.Row="0"  Name="DeleteInputPhotosButton"  HorizontalAlignment="Left" Margin="33,0,0,-2" VerticalAlignment="Top" Width="27" Background="{x:Null}" BorderBrush="{x:Null}" Height="25" Click="DeleteAllInputPhotos_OnClick">
                                        <ContentControl Content="{StaticResource DeleteIcon}" Height="20"/>
                                    </Button>
                                </Grid>
                            </Border>
                            <DataGrid AutoGenerateColumns="False" Grid.Row="0" HorizontalAlignment="Stretch" Name="Photos" Margin="10,43,10,10" SelectionMode="Single" SelectionChanged="Photos_SelectionChanged" IsReadOnly="True" ItemsSource="{Binding DropImages}">
                                <DataGrid.Columns>
                                    <DataGridTextColumn Header="Имя файла" Binding="{Binding Name}"/>
                                    <DataGridTextColumn Header="Горизонтальный диаметр, px" Binding="{Binding XDiameterInPixels}"/>
                                    <DataGridTextColumn Header="Вертикальный диаметр, px" Binding="{Binding YDiameterInPixels}"/>
                                    <DataGridTextColumn Header="Горизонтальный диаметр, м" Binding="{Binding Drop.XDiameterInMeters}" />
                                    <DataGridTextColumn Header="Вертикальный диаметр, м" Binding="{Binding Drop.YDiameterInMeters}"/>
                                    <DataGridTextColumn Header="Радиус, м" Binding="{Binding Drop.RadiusInMeters}"/>
                                    <DataGridTextColumn Header="Объем, кубические метры" Binding="{Binding Drop.VolumeInCubicalMeters}"/>
                                    <DataGridTemplateColumn>
                                        <DataGridTemplateColumn.CellTemplate>
                                            <DataTemplate>
                                                <Button Name="EditInputPhotoButton"  HorizontalAlignment="Left" VerticalAlignment="Top" Width="27" Background="{x:Null}" BorderBrush="{x:Null}" Height="25" Click="EditInputPhotoButton_Click">
                                                    <ContentControl Content="{StaticResource EditIcon}" Height="20"/>
                                                </Button>
                                            </DataTemplate>
                                        </DataGridTemplateColumn.CellTemplate>
                                    </DataGridTemplateColumn>
                                    <DataGridTemplateColumn>
                                        <DataGridTemplateColumn.CellTemplate>
                                            <DataTemplate>
                                                <Button Name="DeleteSingleInputPhotoButton"  HorizontalAlignment="Left" VerticalAlignment="Top" Width="27" Background="{x:Null}" BorderBrush="{x:Null}" Height="25" Click="DeleteSingleInputPhotoButton_Click">
                                                    <ContentControl Content="{StaticResource DeleteIcon}" Height="20"/>
                                                </Button>
                                            </DataTemplate>
                                        </DataGridTemplateColumn.CellTemplate>
                                    </DataGridTemplateColumn>
                                </DataGrid.Columns>
                            </DataGrid>
                            <GridSplitter HorizontalAlignment="Stretch" 
                                  VerticalAlignment="Center" 
                                  Grid.Row="1" ResizeBehavior="PreviousAndNext"
                                  Height="5"/>
                            <utility:ZoomBorder Grid.Row="2" HorizontalAlignment="Stretch" x:Name="CgsImageViewer" ClipToBounds="True" Background="Gray" Margin="10,10,13,10">
                                <Image x:Name="ImgCurrent" VerticalAlignment="Center" HorizontalAlignment="Center" />
                            </utility:ZoomBorder>
                        </Grid>
                    </TabItem>
                    <TabItem Header="Референс">
                        <Grid Background="#FFE5E5E5">
                            <Grid>
                                <Border Name="Border" BorderThickness="1" BorderBrush="#34558b" Margin="10,44,10,10">
                                    <utility:ZoomBorder x:Name="border" ClipToBounds="True" Background="Gray">
                                        <Canvas Name="CanDrawing"
                                        MouseMove="canDrawing_MouseMove_NotDown"
                                        MouseDown="canDrawing_MouseDown">
                                            <Image VerticalAlignment="Stretch"
                                           HorizontalAlignment="Stretch" Stretch="Uniform" Name="ReferenceImage" Canvas.Left="0" Canvas.Top="0"/>
                                        </Canvas>
                                    </utility:ZoomBorder>
                                </Border>
                            </Grid>
                            <Button Click="ChooseReference_OnClick" Content="Выбрать референс" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="109"/>
                            <TextBox Name="PixelsInMillimeterTextBox" Height="20" Margin="0,10,10,0" TextWrapping="Wrap"  VerticalAlignment="Top" HorizontalAlignment="Right" Width="120"/>
                            <Label Content="Пикселей в миллиметре:" Margin="0,7,135,0" VerticalAlignment="Top" Height="30" Background="{x:Null}" HorizontalAlignment="Right" Width="147"/>
                            <Button Name="DeleteButton"  HorizontalAlignment="Left" Margin="124,7,0,0" VerticalAlignment="Top" Width="27" Background="{x:Null}" BorderBrush="{x:Null}" Height="25" Click="DeleteButton_Click">
                                <ContentControl Content="{StaticResource DeleteIcon}" Height="20"/>
                            </Button>
                            <TextBox x:Name="IntervalBetweenPhotos" Height="20" Margin="0,10,287,0" TextWrapping="Wrap"  VerticalAlignment="Top" HorizontalAlignment="Right" Width="115"/>
                            <Label Content="Интервал между снимками:" Margin="0,7,407,0" VerticalAlignment="Top" Height="30" Background="{x:Null}" HorizontalAlignment="Right" Width="163"/>
                        </Grid>
                    </TabItem>
                    <TabItem Header="График">

                    </TabItem>
                </TabControl>
            </TabItem>
            <TabItem Header="Общий график серий">

            </TabItem>
            <ComboBox Height="100" Width="120"/>
        </TabControl>

        <Menu Height="22" Margin="10,10,10,0" VerticalAlignment="Top">
            <MenuItem Width="50" Height="22" Header="Меню">
                <MenuItem Header="Сохранить серию">
                    <MenuItem.Icon>
                        <Rectangle Fill="#34558b" Margin="2,1,0,1" RenderTransformOrigin="0.704,0.315">
                            <Rectangle.OpacityMask>
                                <VisualBrush Stretch="Fill" Visual="{StaticResource SaveIcon}" />
                            </Rectangle.OpacityMask>
                        </Rectangle>
                    </MenuItem.Icon>
                </MenuItem>
                <MenuItem Header="Опции" Click="Options_OnClick">
                    <MenuItem.Icon>
                        <Rectangle Fill="#34558b" Margin="2,1,0,1" RenderTransformOrigin="0.704,0.315">
                            <Rectangle.OpacityMask>
                                <VisualBrush Stretch="Fill" Visual="{StaticResource SettingsIcon}" />
                            </Rectangle.OpacityMask>
                        </Rectangle>
                    </MenuItem.Icon>
                </MenuItem>
                <MenuItem Header="Выйти" Click="MenuItem_OnClick"/>
            </MenuItem>
            <MenuItem Click="Calculate_OnClick" Header="Рассчитать"/>
        </Menu>
        <Grid Margin="10,0,10,10" Background="#FFF0F0F0" Height="32" VerticalAlignment="Bottom">
            <ProgressBar Height="12" Margin="0,0,10,10" VerticalAlignment="Bottom" HorizontalAlignment="Right" Width="100"/>
        </Grid>
    </Grid>
</Window>
...