2014-09-24 65 views
1

我想綁定視頻預覽自定義控件類中的IntPtr VidHandle屬性到它的視圖模型(vm:DebugHiResCameraWindowViewModel)中的IntPtr PreviewHandle。ViewModel屬性沒有更新時,它是相應的CustomControl屬性更新

在VideoPreview的構造,我呼籲:

this.VidHandle = picBox.Handle; 

更新VideoPreview的VidHandleProperty的DependencyProperty。這工作完美。但是,ViewModel中的PreviewHandle屬性未被更新。到時候我打電話:

camera.StartVideoStream(PreviewHandle); 

在視圖模型,PreviewHandle是0,因爲它從來沒有從VideoPreview更新。我有感覺我的DependencyProperty VidHandleProperty沒有正確實現,但我可能是錯的。

下面是一些代碼片段:

主窗口XAML:

<Window 
x:Class="AoiImageLift.Views.DebugHiResCameraWindow" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
xmlns:vm="clr-namespace:AoiImageLift.Presentation.ViewModels" 
xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms" 
xmlns:com="clr-namespace:AoiImageLift.Components" 
xmlns:local="clr-namespace:AoiImageLift" 
Title="DebugHiResCameraWindow" 
Name="hiResWindow" 
Height="300" 
Width="300"> 
<Window.Resources> 
    <vm:DebugHiResCameraWindowViewModel x:Key="viewModel"/> 
</Window.Resources> 
<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition/> 
     <RowDefinition/> 
    </Grid.RowDefinitions> 

    <com:VideoPreview 
     DataContext="{StaticResource viewModel}" 
     x:Name="videoHost" 
     VidHandle="{Binding PreviewHandle, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type com:VideoPreview}}}"/> 

    <Button 
     DataContext="{StaticResource viewModel}" 
     Grid.Row="1" 
     Width="100" 
     Height="40" 
     Command="{Binding StartCaptureCommand}" 
     Content="Start"/> 
</Grid> 

VideoPreview類:

public class VideoPreview : WindowsFormsHost 
{ 
    private PictureBox picBox; 
    public static readonly DependencyProperty VidHandleProperty = 
     DependencyProperty.Register(
      "VidHandle", 
      typeof(IntPtr), 
      typeof(VideoPreview), 
      new FrameworkPropertyMetadata 
      { 
       BindsTwoWayByDefault = true 
      }); 

    public VideoPreview() : base() 
    { 
     picBox = new PictureBox(); 
     picBox.Width = (int) this.Width; 
     picBox.Height = (int) this.Height; 

     this.VidHandle = picBox.Handle; 
     this.Child = picBox; 
    } 

    public IntPtr VidHandle 
    { 
     get 
     { 
      return (IntPtr) GetValue(VideoPreview.VidHandleProperty); 
     } 
     set 
     { 
      SetValue(VideoPreview.VidHandleProperty, value); 
     } 
    } 
} 

視圖模型類:

public class DebugHiResCameraWindowViewModel : ViewModel 
{ 
    private Uri capturedImage; 
    private BitmapImage bmp; 
    private ISnapImages camera; 

    public DebugHiResCameraWindowViewModel() 
    { 
     camera = LumeneraCamera.Instance; 
     bmp = new BitmapImage(); 
    } 

    public IntPtr PreviewHandle { get; set; } 
    public Uri CapturedImage 
    { 
     get { return capturedImage; } 
     set { capturedImage = value; OnPropertyChanged("CapturedImage"); } 
    } 
    public ICommand StartCaptureCommand 
    { 
     get 
     { 
      return new DelegateCommand(() => 
      { 
       try 
       { 
        camera.StartVideoStream(PreviewHandle); 
       } 
       catch (CustomException ex) 
       { 
        MessageBox.Show(ex.Message, ex.Caption, ex.Button, ex.Image); 
       } 
      }); 
     } 
    } 
} 
+0

該控件的構造函數中的'this.VidHandle = picBox.Handle;'行在綁定前執行'VidHandle =「{Binding PreviewHandle ...''成立。因此綁定將簡單地覆蓋'VidHandle'的值。你也許可以在'VidHandle'改變回調的屬性中設置'picBox.Handle'。 – Clemens 2014-09-24 20:51:19

回答

1

看起來VideoPreview控件的VidHandle控件綁定到您的VideoPreview控件的PreviewHandle(它不存在)。

開始調試時檢查輸出窗口,它會顯示綁定錯誤(例如,當它找不到屬性時)。

也許這是你以後?

<Window 
x:Class="AoiImageLift.Views.DebugHiResCameraWindow" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
xmlns:vm="clr-namespace:AoiImageLift.Presentation.ViewModels" 
xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms" 
xmlns:com="clr-namespace:AoiImageLift.Components" 
xmlns:local="clr-namespace:AoiImageLift" 
Title="DebugHiResCameraWindow" 
Name="hiResWindow" 
Height="300" 
Width="300"> 
<!-- CHANGED HERE: set DataContext of Window --> 
<Window.DataContext> 
    <vm:DebugHiResCameraWindowViewModel /> 
</Window.DataContext> 
<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition/> 
     <RowDefinition/> 
    </Grid.RowDefinitions> 

    <!-- CHANGED HERE: removed DataContext (set at Window) -- updated binding --> 
    <com:VideoPreview 
     x:Name="videoHost" 
     VidHandle="{Binding PreviewHandle}"/> 

    <!-- CHANGED HERE: removed DataContext (set at Window) -- binding OK --> 
    <Button 
     Grid.Row="1" 
     Width="100" 
     Height="40" 
     Command="{Binding StartCaptureCommand}" 
     Content="Start"/> 
</Grid> 

DataContext的是繼承,你可以在窗口中設置它,它會由子控件是已知的。

回覆:評論......虛擬機通常會優先 - 如果您在所有獲取/設置者上設置斷點,您可以看到該命令...... 0來自DP的默認值(可以是因爲DP是靜態的,所以它不能是PictureBox)。不知道這是適當的,但它的工作原理:

在你VideoPreview構造函數中添加:

base.Loaded += VideoPreview_Loaded; 

,並添加

void VideoPreview_Loaded(object sender, RoutedEventArgs e) 
{ 
    this.VidHandle = picBox.Handle; 
} 

在視圖中,更新綁定:

VidHandle="{Binding PreviewHandle, UpdateSourceTrigger=PropertyChanged}" 

您可能還想要Mode=OneWayToSource,假設手柄只能回來m VideoPreview

+0

感謝您的迴應,但是當我做出這些更改時,DebugHiResCameraWindowViewModel的PreviewHandle屬性仍然爲0,當我單擊按鈕時,它告訴我VideoPreview類中的VidHandle的值不是對視圖模型中的綁定屬性。我的VideoPreview自定義控件類是否正確實現?我不需要更新視圖模型? – kformeck 2014-09-24 20:02:33

+0

在答案底部看到更新 – bdimag 2014-09-24 20:50:45

+1

您的更改完美無缺!關鍵是在OnLoaded事件處理程序中設置VideoPreview類的VidHandle,而不是在構造函數中。 – kformeck 2014-09-25 14:37:41