程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> Windows 7 開發:傳感器 - 管理(動手實驗)(二)

Windows 7 開發:傳感器 - 管理(動手實驗)(二)

編輯:關於.NET

任務 5 –將ViewModel 和傳感器助手進行整合

1.打開 SensorViewModel.cs ,並且在私有區域創建一個屬性來暴露光線傳感器。

C#

private SensorHelper<AmbientLightSensor, AmbientLightSensor.LuminousIntensity> _sensor;
public SensorHelper<AmbientLightSensor, AmbientLightSensor.LuminousIntensity>
                 LightSensor
     {
                 get { return _sensor; }
     }

2.現在我們來對加速傳感器做相同的事。

C#

private SensorHelper<Accelerometer3D, Accelerometer3D.Acceleration3D>
                 _acceleromaterSensor;
public SensorHelper<Accelerometer3D, Accelerometer3D.Acceleration3D>
                 AcceleromaterSensor
     {
                 get { return _acceleromaterSensor; }
     }

3.我們為SensorViewModel加入一個結構體,用來設置傳感器。

C#

public SensorViewModel()
                 {
                 _sensor = new SensorHelper<AmbientLightSensor,
                                                 AmbientLightSensor.LuminousIntensity>();
                       _sensor.Initialize();
                       _acceleromaterSensor = new SensorHelper<Accelerometer3D,
                                 Accelerometer3D.Acceleration3D>();
                       _acceleromaterSensor.Initialize();
                 }

4.編譯並測試你的代碼。你應該能夠運行並且與傳感器進行整合。

任務 6 – 在UI 用戶界面添加光纖傳感器的交互。

在下面的任務中,你將使用到光線亮度傳感器。三個獨立的元素將與其進行交互:

•  亮度指示器:一個衡量光線亮度的進度條

•  圖像:當亮度增強的時候,一半圖片將變成灰色。

•  圖像名稱:在高亮的狀態下增大字號來保持可讀性。

1.添加第一個傳感器指示器,轉到MainWindow.xaml,並且定位到布局grid的左邊(包含了一個標題叫“Sensor Data”的)。

XAML

<TextBlock HorizontalAlignment="Center" Margin="0,10" VerticalAlignment="Top" FontFamily="Segoe UI" FontSize="13" Foreground="White" Text="Sensor Data"/>
<Grid Margin="9,36,9,9">
  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="2*"/>
    <ColumnDefinition Width="1*"/>
    <ColumnDefinition Width="1*"/>
    <ColumnDefinition Width="1*"/>
    <ColumnDefinition Width="0.4*"/>            </Grid.ColumnDefinitions>
<Grid.RowDefinitions>
    <RowDefinition Height="*"/>
    <RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Border Grid.ColumnSpan="5" Grid.RowSpan="2" Background="Black" CornerRadius="2"/>
<TextBlock Grid.Column="0" Grid.Row="2" HorizontalAlignment="Center" Margin="4,0,4,10" VerticalAlignment="Center" Foreground="White" Text="LUM"/>

<ProgressBar x:Name="LightIntensityProgressBar" Width="10" HorizontalAlignment="Center" Margin="0,8,0,5" Maximum="1" Minimum="0" Orientation="Vertical" 
Style="{StaticResource SensorProgressBar}" 
Value="{Binding Path=LightSensor.Value.Intensity, Mode=OneWay, Converter={StaticResource LuminosityConverter}}"/>
  <Path Height="80" Grid.ColumnSpan="5" Grid.RowSpan="2" Margin="1,0" VerticalAlignment="Top" Data="M0.5,0.5L214.5,0.5 214.5,168.5 212.8,168.4C197.7,167.1 181.8,166.5 165.5,166.5 95.3,166.5 34.0,178.9 1.3,197.3L0.5,197.8z" Stretch="Fill">
     <Path.Fill>
      <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
        <GradientStop Offset="0" Color="#04FFFFFF"/>
        <GradientStop Offset="0.1" Color="#10FFFFFF"/>
                  <GradientStop Offset="1.0" Color="#18FFFFFF"/>
      </LinearGradientBrush>
    </Path.Fill>
  </Path>
</Grid>

2.為了我們的數據綁定工作,我們需要創建一個數據轉換器,用來在傳感器數據和進度條控件中進行轉換。那麼我們可以在MainWindow.xaml.cs文件中添加一個轉換器的類。

C#

public class LuminosityConverter : IValueConverter
{
    #region IValueConverter Members
    public object Convert(object value, Type targetType,
                 object parameter, 
                 System.Globalization.CultureInfo culture)
    {
      double d = System.Convert.ToDouble(value);
      return Math.Max(Math.Min(Math.Log(d, 10000), 1.0), 0.0);
    }

    public object ConvertBack(object value, Type targetType, 
                object parameter, System.Globalization.CultureInfo culture)
    {
      throw new NotImplementedException();
    }
    #endregion
 }

3.在我們已經創建了LuminosityConverter類之後,我們需要將它聲明為一個資源。返回到MainWindow.xaml,並且“local”XAML命名空間的聲明要和轉換器的命名空間相同。

XAML

<Window x:Class="SensorHOL.MainWindow"
xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation
xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml
xmlns:local="clr-namespace:SensorHOL"
Title="MainWindow" WindowState="Maximized" Background="Black">

4.在Windows��件中添加一個資源塊。

XAML

<Window.Resources>
</Window.Resources>

5.在資源塊中,聲明一個Converter資源。

XAML

<local:LuminosityConverter x:Key="LuminosityConverter" />

6.編譯並且運行應用程序。

你將看到燈光指示器能夠反映光線傳感器。

7.現在將這個與其他的我們希望它們與之交互的元素進行連接。

a.首先,改變圖片名稱的字體大小。

那麼在光線測量值和字體大小間的轉換,又一次的用到了轉換器。

b.然後,定位到ImageName的文本區域。

(請注意,我們對之前實現的進度條已經進行了綁定)。

XAML

<TextBlock Foreground="White" Grid.Column="1" Grid.Row="2" HorizontalAlignment="Center" VerticalAlignment="Center" FontFamily="Segoe UI" FontSize="{Binding ElementName=LightIntensityProgressBar, Path=Value, Mode=OneWay, Converter={StaticResource LuminosityToFontSizeConverter}}"  Text="{Binding ImageName, Mode=OneWay}"/>

8.轉到轉換器的後台代碼實現。

C#

public class LuminosityToFontSizeConverter : IValueConverter
  {
    #region IValueConverter Members

    public object Convert(object value, Type targetType, object
                parameter, System.Globalization.CultureInfo culture)
                {
                double d = System.Convert.ToDouble(value);
                      return 70.0 * d + 13.0;
                }

    public object ConvertBack(object value, Type targetType, object     parameter, System.Globalization.CultureInfo culture)    
{
                throw new NotImplementedException();
}
    #endregion
  }

9.現在,將這個轉換器聲明成一個資源。

XAML

<Window.Resources>
    <local:LuminosityConverter x:Key="LuminosityConverter" />
    <local:LuminosityToFontSizeConverter
                x:Key="LuminosityToFontSizeConverter" />
</Window.Resources>

10.編譯並運行代碼。

當光線增強的時候,圖片名稱的文字應該變大。

現在將圖片連接到光線指示器,並且允許圖片使用灰白效果。

11.我們從你的開始解決方案中,向PixelShaders添加XAML命名空間開始。

XAML

<Window x:Class="SensorHOL.MainWindow"
xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation
xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml
xmlns:local="clr-namespace:SensorHOL"
xmlns:PixelShaders="clr-namespace:SensorHOL.PixelShaders"
Title="MainWindow" WindowState="Maximized" Background="Black">

12.現在我們可以添加PixelShader元素,並且對第二張圖片添加OpacityMask。

XAML

<Image Source="{Binding ImagePath}" Stretch="Uniform" Margin="10">
</Image>
<Image Source="{Binding ImagePath}" Stretch="Uniform" Margin="10">
    <Image.Effect>
          <PixelShaders:GrayscaleEffect DesaturationFactor="{Binding ElementName=LightIntensityProgressBar, Path=Value, Mode=OneWay, Converter={StaticResource InvertLuminosityConverter}}"/>
    </Image.Effect>
    <Image.OpacityMask>
          <LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
            <GradientStop Offset="{Binding ElementName=OverlayAdjustmentSlider, Path=Value}" Color="#0000"/>
            <GradientStop Offset="{Binding ElementName=OverlayAdjustmentSlider, Path=Value}" Color="#F000"/>
          </LinearGradientBrush>
   </Image.OpacityMask>
</Image>

13.同樣,在光線測量值和PixelShader值之前,實現一個數據轉換器。

C#

public class InvertLuminosityConverter : IValueConverter
  {
    #region IValueConverter Members
    public object Convert(object value, Type targetType,
                 object parameter, System.Globalization.CultureInfo culture)
    {
                double d = System.Convert.ToDouble(value);
                      return 1 - d;
    }
    public object ConvertBack(object value, Type targetType,
                 object parameter, System.Globalization.CultureInfo culture)
    {
                throw new NotImplementedException();
    }
    #endregion
  }

14.和我們創建完轉換器一樣,我們還需要將其指定為一個資源。

XAML

<Window.Resources>
    <local:LuminosityConverter x:Key="LuminosityConverter" />
    <local:LuminosityToFontSizeConverter
                x:Key="LuminosityToFontSizeConverter" />
    <local:InvertLuminosityConverter x:Key="InvertLuminosityConverter" />
  </Window.Resources>

15.編譯並運行你的代碼。現在你應該已經可以使用滑塊來控制圖片,並且其中一部分的圖片將與傳感器進行交互,展示灰白的圖片。

任務 7 – 將加速傳感器與UI 用戶界面進行整合(可選)

在這個任務中,你將會把3D加速傳感器與UI用戶界面進行連接。另外,還有左邊的加速器指示器,右邊的應用程序隨每個傳感器運動進行的旋轉。

1.首先,你要實現X,Y,Z軸的運動指示器:

a.在MainWindow.xaml中,找到LightIntensityProgressBar。

b.如果想要做這個,再添加3個指示器。

其實他們在代碼上看很清楚,因為所有3個指示器都綁定到同一個屬性,我們只需要一種方法來區分每個指示器。這個就是通過轉換進程來關心這個問題的轉換器元素的目的。

XAML

<TextBlock Grid.Column="0" Grid.Row="2" HorizontalAlignment="Center" Margin="4,0,4,10" VerticalAlignment="Center" Foreground="White" Text="LUM"/>
<ProgressBar x:Name="LightIntensityProgressBar" Width="10" HorizontalAlignment="Center" Margin="0,8,0,5" Maximum="1" Minimum="0" Orientation="Vertical" Style="{StaticResource SensorProgressBar}" Value="{Binding Path=LightSensor.Value.Intensity, Mode=OneWay, Converter={StaticResource LuminosityConverter}}"/>

<TextBlock Grid.Column="1" Grid.Row="2" HorizontalAlignment="Center" Margin="4,0,4,10" VerticalAlignment="Center" Foreground="White" Text="X"/>
<ProgressBar x:Name="AccelerometerX" Width="10" Grid.Column="1" HorizontalAlignment="Center" Margin="0,8,0,5" Maximum="1.3" Minimum="-1.3" Orientation="Vertical" Style="{StaticResource SensorProgressBar}" Value="{Binding Path=AcceleromaterSensor.Value, Mode=OneWay, Converter={StaticResource AccelerationConverter}, ConverterParameter=X}"/>

<TextBlock Grid.Column="2" Grid.Row="2" HorizontalAlignment="Center" Margin="4,0,4,10" VerticalAlignment="Center" Foreground="White" Text="Y"/>
<ProgressBar x:Name="AccelerometerY" Width="10" Grid.Column="2" HorizontalAlignment="Center" Margin="0,8,0,5" Maximum="1.3" Minimum="-1.3" Orientation="Vertical" Style="{StaticResource SensorProgressBar}" Value="{Binding Path=AcceleromaterSensor.Value, Mode=OneWay, Converter={StaticResource AccelerationConverter}, ConverterParameter=Y}"/>

<TextBlock Grid.Column="3" Grid.Row="2" HorizontalAlignment="Center" Margin="4,0,4,10" VerticalAlignment="Center" Foreground="White" Text="Z"/>
<ProgressBar x:Name="AccelerometerZ" Width="10" Grid.Column="3" HorizontalAlignment="Center" Margin="0,8,0,5" Maximum="1.3" Minimum="-1.3" Orientation="Vertical" Style="{StaticResource SensorProgressBar}" Value="{Binding Path=AcceleromaterSensor.Value, Mode=OneWay, Converter={StaticResource AccelerationConverter}, ConverterParameter=Z}"/>

2.現在我們可以添加一個使用轉換元素的數據轉換器,但是首先我們需要添加下面的引用部分。

C#

using Microsoft.WindowsAPICodePack.Sensors;

3.添加下面的代碼。

C#

public class AccelerationConverter : IValueConverter
{
    #region IValueConverter Members
    public object Convert(object value, Type targetType, object
                                parameter, System.Globalization.CultureInfo culture)
    {
      Accelerometer3D.AccelerationAxis? axis = 
                (Accelerometer3D.AccelerationAxis?)Enum.Parse(typeof(Acceleromete         r3D.AccelerationAxis), parameter as string);
      if (axis.HasValue)
      {
        var a3d = value as Accelerometer3D.Acceleration3D;
        if (a3d != null)
          return a3d[axis.Value];
      }
      return 0.0;
    }
    public object ConvertBack(object value, Type targetType, object
                                parameter, System.Globalization.CultureInfo culture)
    {
      throw new NotImplementedException();
    }
    #endregion
  }

4.添加數據轉換器資源聲明。

XAML

<Window.Resources>
    <local:LuminosityConverter x:Key="LuminosityConverter" />
    <local:LuminosityToFontSizeConverter x:Key="LuminosityToFontSizeConverter" />
    <local:InvertLuminosityConverter x:Key="InvertLuminosityConverter" />
    <local:AccelerationConverter x:Key="AccelerationConverter" />  </Window.Resources>

現在我們就可以使用3D加速器傳感器,和屏幕上的旋轉元素了。

我們使用WPF中的使用角度來進行旋轉。轉換器將加速器的X軸和Y軸轉換成角度。為了保證旋轉有效的工作,必須將它設置在元素的中央。這就是為什麼我們還有一個專門計算元素中央位置的轉換器。

5.為每一個圖片添加下面的代碼片段。

XAML

<Image.RenderTransform>
  <RotateTransform 
Angle="{Binding Path=AcceleromaterSensor.Value, Mode=OneWay, Converter={StaticResource DegreesFromAcceleratorConverter}}" CenterX="{Binding RelativeSource={RelativeSource AncestorType={x:Type Image}, AncestorLevel=1}, Path=ActualWidth, Converter={StaticResource DoubleSplitConverter}}" 

CenterY="{Binding RelativeSource={RelativeSource AncestorType={x:Type Image}, AncestorLevel=1}, Path=ActualHeight, Converter={StaticResource DoubleSplitConverter}}" />

</Image.RenderTransform>

6.在Slider元素中,添加下面的代碼片段(與上面的代碼非常相似)。

XAML

<Slider.RenderTransform>
   <RotateTransform 
Angle="{Binding Path=AcceleromaterSensor.Value, Mode=OneWay, Converter={StaticResource DegreesFromAcceleratorConverter}}" 

CenterX="{Binding RelativeSource={RelativeSource AncestorType={x:Type Slider}, AncestorLevel=1}, Path=ActualWidth, Converter={StaticResource DoubleSplitConverter}}" 

CenterY="{Binding RelativeSource={RelativeSource AncestorType={x:Type Slider}, AncestorLevel=1}, Path=ActualHeight, Converter={StaticResource DoubleSplitConverter}}"/>

</Slider.RenderTransform>

7.實現第一個轉換器,DegreesFromAcceleratorConverter。

C#

public class DegreesFromAcceleratorConverter : IValueConverter
  {
    private double _prevX;
    private double _prevY;
    private const double _histCoeff = 0.6;
    private const double _threshold = 0.1;
    private bool _prevValuesInit;

    #region IValueConverter Members

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
      var a3d = value as Accelerometer3D.Acceleration3D;
      if (a3d != null)
      {
        double x = a3d[Accelerometer3D.AccelerationAxis.X];
        double y = a3d[Accelerometer3D.AccelerationAxis.Y];

        if (!_prevValuesInit)
        {
          _prevValuesInit = true;
          _prevX = x;
          _prevY = y;
        }
        if (Math.Abs(_prevX - x) < _threshold)
          x = _prevX;
        if (Math.Abs(_prevY - y) < _threshold)
          y = _prevY;

        _prevX = (_histCoeff * _prevX) + (1.0 - _histCoeff) * x;
        _prevY = (_histCoeff * _prevY) + (1.0 - _histCoeff) * y;

        double radians = Math.Atan2(_prevX, -_prevY);
        return radians * 180 / Math.PI;
      }
      return 0.0;
    }
    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
      throw new NotImplementedException();
    }
    #endregion
  }

8.現在添加第二個轉換器。

C#

public class DoubleSplitConverter : IValueConverter
  {
    #region IValueConverter Members
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
      double doubleValue = System.Convert.ToDouble(value);
      return doubleValue/2.0;
    }
    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
      throw new NotImplementedException();
    }
    #endregion
 }

9.所有剩下的你需要做的,就是將那些轉換器聲明成資源。

XAML

<local:DoubleSplitConverter x:Key="DoubleSplitConverter" /> <local:DegreesFromAcceleratorConverter x:Key="DegreesFromAcceleratorConverter" />

10.編譯並運行你的代碼。

你現在應該可以使用滑塊來單獨控制每個圖片的旋轉了。

你可以在Final解決方案文件夾中找到這個項目的最終版。做得好!

將Windows 7傳感器支持整合到你的應用程序中,通過使應用程序能夠對周圍環境作出更快更好的反應,將大大提高你的應用程序的機會。在這個實驗中,你已經創建了一個WPF應用程序,並且通過整合不同的傳感器,制造了令人興奮的UI用戶界面體驗。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved