none
如何把现场拍照功能做到MVVM的ViewModel里面 RRS feed

  • 问题

  • 现场拍照xaml代码:

    <Border Grid.Row="2" BorderBrush="#8c8e94" BorderThickness="0,0,0,1">
                            <StackPanel Name="TakePhotoStackPanel" Orientation="Vertical" VerticalAlignment="Stretch"  Margin="10 10 10 10">
                                <StackPanel Orientation="Horizontal">
                                    <TextBlock Text="现场拍照" FontSize="18" VerticalAlignment="Center" HorizontalAlignment="Left"/>
                                    <ComboBox Name="cb" SelectionChanged="cb_SelectionChanged" Width="130" Height="25" BorderThickness="0,0,0,0"></ComboBox>
                                    <!--选摄像头-->
                                    <Button Width="83" Height="36" BorderThickness="0 0 0 0" Margin="20,0,0,0" Content="拍照" Name="CaptureButton" Click="CaptureButton_Click" Style="{DynamicResource SearchButton}" HorizontalAlignment="Right">
                                    </Button>
                                    <Button Width="83" Height="36" BorderThickness="0 0 0 0" Margin="20,0,0,0" Content="重拍" Name="NewCaptureButton" Click="NewCaptureButton_Click" Style="{DynamicResource SearchButton}" HorizontalAlignment="Right">
                                    </Button>
                                </StackPanel>
                                <StackPanel Orientation="Horizontal" Margin="0 10 0 0">
                                    <Border Grid.Row="1" Grid.Column="4" Grid.RowSpan="4" Margin="10 0 5 0" BorderBrush="#e8e8e8" BorderThickness="1,1,1,1">
                                        <WPFMediaKit:VideoCaptureElement Width="260" Height="200" Name="vce" HorizontalAlignment="Center"></WPFMediaKit:VideoCaptureElement>
                                    </Border>
                                    <TextBlock Name="TakePhotoStatus" FontSize="18" Margin="0 60 0 0" FontWeight="Bold" FontFamily="微软雅黑"></TextBlock>
                                </StackPanel>
                            </StackPanel>
                        </Border>

    现场拍照后台cs代码:

    private void CaptureButton_Click(object sender, RoutedEventArgs e)
            {
                if (cb.SelectedIndex < 0)
                {
                    TakePhotoStatus.Foreground = Brushes.Red;
                    TakePhotoStatus.Text = "× 摄像头当前不可用";
                }
                else
                {
                    //captureElement. 怎么抓取高清的原始图像           
                    RenderTargetBitmap bmp = new RenderTargetBitmap(
                        (int)vce.ActualWidth,
                        (int)vce.ActualHeight,
                        96, 96, PixelFormats.Default);
                    bmp.Render(vce);

                    BitmapEncoder encoder = new JpegBitmapEncoder();
                    encoder.Frames.Add(BitmapFrame.Create(bmp));
                    using (MemoryStream ms = new MemoryStream())
                    {
                        encoder.Save(ms);
                        captureData = ms.ToArray();
                    }
                    vce.Pause();
                    TakePhotoStatus.Foreground = Brushes.Green;
                    TakePhotoStatus.Text = "√ 照片拍摄完成";
                }
            }

    现在我想把这个页面改成MVVM模式,所以就需要这个拍照功能做到ViewModel里面,那这个该如何现实才好,前台应该怎么绑定图像,或者viewmodel里如何操作拍照控件呢?

    • 已移动 Bob Ding 2018年3月2日 5:11 第三方控件相关
    2018年2月28日 9:12

答案

  • 你好,

    你说的VideoCaptureElement 控件是第三方的控件在这个论坛是不被支持的,如果你想知道如果使用这个控件,请查阅该控件的相关文档。

    也许在GitHub上问这个问题是最好的地方。

    https://github.com/Sascha-L/WPF-MediaKit

    因为你的问题关于第三方控件,你的问题将被移到一般讨论区。

    Best Regards,

    Bob


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    谢谢,暂时先通过传控件的方式解决了。
    2018年3月3日 4:02

全部回复

  • Hi,

    请使用命令来代替事件。

    在ViewModel中定义一个BitmapImage类型的属性以及一个命令。绑定BitmapImage到image元素的source上. 命令绑定到Button.

     public class VM:DependencyObject
        {
            public BitmapImage DisplayImage
            {
                get { return (BitmapImage)GetValue(DisplayImageProperty); }
                set { SetValue(DisplayImageProperty, value); }
            }
    
            // Using a DependencyProperty as the backing store for DisplayImage.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty DisplayImageProperty =
                DependencyProperty.Register("DisplayImage", typeof(BitmapImage), typeof(VM), new PropertyMetadata(null));
    
            private ICommand _captureCommand;
            public ICommand CaptureCommand
            {
                get
                {
                    if (_captureCommand == null)
                    {
                        _captureCommand = new RelayCommand(
                            param => 
                            {
                                //捕捉视频
    
                                //设置DisplayImage
    
                            }, param => true);
                    }
                    return _captureCommand;
                } 
            }
        }
        public class RelayCommand : ICommand
        {
            private Predicate<object> _canExecute;
            private Action<object> _execute;
    
            public RelayCommand(Action<object> execute, Predicate<object> canExecute)
            {
                this._canExecute = canExecute;
                this._execute = execute;
            }
    
            public event EventHandler CanExecuteChanged
            {
                add { CommandManager.RequerySuggested += value; }
                remove { CommandManager.RequerySuggested -= value; }
            }
    
            public bool CanExecute(object parameter)
            {
                return _canExecute(parameter);
            }
    
            public void Execute(object parameter)
            {
                _execute(parameter);
            }
        }
    
      <Image Source="{Binding BitmapImage}"/>
            <Button Command="{Binding CapturePic}" CommandParameter="{Binding something}"/>

    你可以将你需要的东西作为命令参数传递给ViewModel, 甚至可以把整个“拍照控件”传到ViewModel,但显然没有这个必要,只需传递需要的数据集合。

    Best Regards,

    Bob


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2018年3月1日 8:26
  • Hi,

    请使用命令来代替事件。

    在ViewModel中定义一个BitmapImage类型的属性以及一个命令。绑定BitmapImage到image元素的source上. 命令绑定到Button.

     public class VM:DependencyObject
        {
            public BitmapImage DisplayImage
            {
                get { return (BitmapImage)GetValue(DisplayImageProperty); }
                set { SetValue(DisplayImageProperty, value); }
            }
    
            // Using a DependencyProperty as the backing store for DisplayImage.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty DisplayImageProperty =
                DependencyProperty.Register("DisplayImage", typeof(BitmapImage), typeof(VM), new PropertyMetadata(null));
    
            private ICommand _captureCommand;
            public ICommand CaptureCommand
            {
                get
                {
                    if (_captureCommand == null)
                    {
                        _captureCommand = new RelayCommand(
                            param => 
                            {
                                //捕捉视频
    
                                //设置DisplayImage
    
                            }, param => true);
                    }
                    return _captureCommand;
                } 
            }
        }
        public class RelayCommand : ICommand
        {
            private Predicate<object> _canExecute;
            private Action<object> _execute;
    
            public RelayCommand(Action<object> execute, Predicate<object> canExecute)
            {
                this._canExecute = canExecute;
                this._execute = execute;
            }
    
            public event EventHandler CanExecuteChanged
            {
                add { CommandManager.RequerySuggested += value; }
                remove { CommandManager.RequerySuggested -= value; }
            }
    
            public bool CanExecute(object parameter)
            {
                return _canExecute(parameter);
            }
    
            public void Execute(object parameter)
            {
                _execute(parameter);
            }
        }
      <Image Source="{Binding BitmapImage}"/>
            <Button Command="{Binding CapturePic}" CommandParameter="{Binding something}"/>

    你可以将你需要的东西作为命令参数传递给ViewModel, 甚至可以把整个“拍照控件”传到ViewModel,但显然没有这个必要,只需传递需要的数据集合。

    Best Regards,

    Bob


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    感谢答复,但是关键还是没有说到这个拍照控件是如何调用的,例如 //捕捉视频 这里,我该怎么去使用<WPFMediaKit:VideoCaptureElement>这个控件,

    另外我用的是Prism框架,所以我的viewmodel中的结构是这样的:

    class CollectInformationViewModel : NotificationObject
    {

            public DelegateCommand CaptureCommand { get; set; }//拍照
            public DelegateCommand ReCaptureCommand { get; set; }//重拍

            //拍照返回状态
            private string takephoneStatus;
            public string TakePhotoStatus
            {
                get { return takephoneStatus; }
                set
                {
                    takephoneStatus = value;
                    this.RaisePropertyChanged("TakePhotoStatus");
                }
            }

    }

    view:

    <Button Width="83" Height="36" BorderThickness="0 0 0 0" Margin="20,0,0,0" Content="拍照" Name="CaptureButton" Command="{Binding CaptureCommand}" Style="{DynamicResource SearchButton}" HorizontalAlignment="Right">
                                    </Button>
                                    <Button Width="83" Height="36" BorderThickness="0 0 0 0" Margin="20,0,0,0" Content="重拍" Name="NewCaptureButton" Command="{Binding ReCaptureCommand}" Style="{DynamicResource SearchButton}" HorizontalAlignment="Right">
                                    </Button>

    <WPFMediaKit:VideoCaptureElement Width="260" Height="200" Name="vce" HorizontalAlignment="Center"></WPFMediaKit:VideoCaptureElement>

    <TextBlock Name="TakePhotoStatus" FontSize="18" Margin="0 60 0 0" FontWeight="Bold" FontFamily="微软雅黑"></TextBlock>

    希望您能说得详细一点,谢谢啦!

    2018年3月2日 4:34
  • 你好,

    你说的VideoCaptureElement 控件是第三方的控件在这个论坛是不被支持的,如果你想知道如果使用这个控件,请查阅该控件的相关文档。

    也许在GitHub上问这个问题是最好的地方。

    https://github.com/Sascha-L/WPF-MediaKit

    因为你的问题关于第三方控件,你的问题将被移到一般讨论区。

    Best Regards,

    Bob


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2018年3月2日 5:10
  • 你好,

    你说的VideoCaptureElement 控件是第三方的控件在这个论坛是不被支持的,如果你想知道如果使用这个控件,请查阅该控件的相关文档。

    也许在GitHub上问这个问题是最好的地方。

    https://github.com/Sascha-L/WPF-MediaKit

    因为你的问题关于第三方控件,你的问题将被移到一般讨论区。

    Best Regards,

    Bob


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    谢谢,暂时先通过传控件的方式解决了。
    2018年3月3日 4:02