【问题标题】:WPF - MVVM - Return Bindable Control Template from View ModelWPF - MVVM - 从视图模型返回可绑定控件模板
【发布时间】:2016-12-19 01:53:19
【问题描述】:

我正在尝试在列表视图上显示可用的 Wifi 网络(使用 ManagedWifi SDK)。

我在视图模型中定义了 WifiNetwork 的 ObservableCollection(包含名称、类型、信号强度(int)等),如下所示

public ObservableCollection<WifiNetwork> AvailableNetworks { get; set; }

我在应用程序资源中定义了控制模板(如 1 个绿条和 4 个白条表示信号强度

<ControlTemplate x:Key="Signal1">
    <Canvas Width="32" Height="32" Canvas.Left="0" Canvas.Top="0">
        <Rectangle Width="5.4375" Height="11.375" Canvas.Left="0.0937499" Canvas.Top="20.6563" Stretch="Fill" StrokeLineJoin="Round" Stroke="#FF000000" Fill="#FF37F307"/>
        <Rectangle Width="6.40625" Height="16" Canvas.Left="5.34375" Canvas.Top="16.0313" Stretch="Fill" StrokeLineJoin="Round" Stroke="#FF000000" Fill="#FFFFFFFF"/>
        <Path Width="6.88835" Height="21.6562" Canvas.Left="11.75" Canvas.Top="10.375" Stretch="Fill" StrokeLineJoin="Round" Stroke="#FF000000" Fill="#FFFFFFFF" Data="F1 M 12.2768,10.875L 18.1384,10.875L 18.1115,31.5313L 12.25,31.5313L 12.2768,10.875 Z "/>
        <Rectangle Width="6.78126" Height="26.9687" Canvas.Left="18.5625" Canvas.Top="5.09376" Stretch="Fill" StrokeLineJoin="Round" Stroke="#FF000000" Fill="#FFFFFFFF"/>
        <Rectangle Width="6.71874" Height="31.8437" Canvas.Left="25.2812" Canvas.Top="0.250002" Stretch="Fill" StrokeLineJoin="Round" Stroke="#FF000000" Fill="#FFFFFFFF"/>
    </Canvas>
</ControlTemplate>

<ControlTemplate x:Key="Signal2">
    <Canvas Width="32" Height="32" Canvas.Left="0" Canvas.Top="0">
        <Rectangle Width="5.4375" Height="11.375" Canvas.Left="0.0937499" Canvas.Top="20.6563" Stretch="Fill" StrokeLineJoin="Round" Stroke="#FF000000" Fill="#FF37F307"/>
        <Rectangle Width="6.40625" Height="16" Canvas.Left="5.34375" Canvas.Top="16.0313" Stretch="Fill" StrokeLineJoin="Round" Stroke="#FF000000" Fill="#FF37F307"/>
        <Path Width="6.88835" Height="21.6562" Canvas.Left="11.75" Canvas.Top="10.375" Stretch="Fill" StrokeLineJoin="Round" Stroke="#FF000000" Fill="#FFFFFFFF" Data="F1 M 12.2768,10.875L 18.1384,10.875L 18.1115,31.5313L 12.25,31.5313L 12.2768,10.875 Z "/>
        <Rectangle Width="6.78126" Height="26.9687" Canvas.Left="18.5625" Canvas.Top="5.09376" Stretch="Fill" StrokeLineJoin="Round" Stroke="#FF000000" Fill="#FFFFFFFF"/>
        <Rectangle Width="6.71874" Height="31.8437" Canvas.Left="25.2812" Canvas.Top="0.250002" Stretch="Fill" StrokeLineJoin="Round" Stroke="#FF000000" Fill="#FFFFFFFF"/>
    </Canvas>
</ControlTemplate>

现在我需要从我的视图模型中返回这个控件模板,以将它绑定到一个按钮,以在我的列表框中显示适当的信号强度。

我可能需要进行某种从信号强度 (int) 到控制模板的转换。

有什么建议/代码示例来完成这个任务吗?

【问题讨论】:

  • 鉴于您的视图 model 不应该了解 WPF,因此您的设计存在更大的问题。

标签: c# wpf mvvm


【解决方案1】:

这应该引导正确的方向:

    <ItemsControl ItemsSource="{Binding AvailableNetworks }">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Rectangle Width="20" Height="{Binding SignalStrength,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
                     Fill="{Binding Color,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"></Rectangle>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>

【讨论】:

    【解决方案2】:

    我喜欢 Darek 的回答,但是如果你真的想使用这样的控制模板,你应该使用绑定到信号强度的样式和数据触发器,例如:

    <Style TargetType="{x:Type MyControl}">
       <Style.Triggers>
           <DataTrigger Binding="{Binding SignalStrength}" Value="1">
              <Setter Property="ControlTemplate" Value="{StaticResource Signal1}"/>
           </DataTrigger>
           <DataTrigger Binding="{Binding SignalStrength}" Value="2">
              <Setter Property="ControlTemplate" Value="{StaticResource Signal2}"/>
           </DataTrigger>
           <!-- and so on -->
       </Style.Triggers>
    </Style>
    

    【讨论】:

      【解决方案3】:

      另一种方法是在列表框上使用 ItemTemplate 并创建一个转换器类。

      创建一个名为 ColorConverter 的公共类并在其中使用以下代码:

      public class ColorConverter : IValueConverter
      {
          #region Implementation of IValueConverter
      
          public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
          {
              try
              {
                  var val = System.Convert.ToInt32(value.ToString());
                  var param = System.Convert.ToInt32(parameter.ToString());
      
                  return val >= param ? Brushes.Green : Brushes.White;
      
              }
              catch
              {
                  return Brushes.White;
              }
          }
      
          public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
          {
              throw new NotImplementedException();
          }
      
          #endregion
      }
      

      然后在带有 ListBox 的页面上分配转换器:

      <Window.Resources>
          <Converters:ColorConverter x:Key="colorConverter" />
      </Window.Resources>
      

      确保将“转换器”的命名空间放在 xaml 的顶部:

      xmlns:Converters="clr-namespace:ProjectNameHere"
      

      然后使用上面的代码在列表框上创建一个 DataTemplate,将绑定替换为正确的形式:

      <ListBox Margin="0,73,0,0" ItemsSource="{Binding AvailableNetworks}">
              <ListBox.ItemTemplate>
                  <DataTemplate>
                      <Canvas Width="32"
                              Height="32"
                              Canvas.Left="0"
                              Canvas.Top="0">
                          <Rectangle Width="5.4375"
                                     Height="11.375"
                                     Canvas.Left="0.0937499"
                                     Canvas.Top="20.6563"
                                     Stretch="Fill"
                                     StrokeLineJoin="Round"
                                     Stroke="#FF000000"
                                     Fill="{Binding Strength, Converter={StaticResource colorConverter}, ConverterParameter=0}" />
                          <Rectangle Width="6.40625"
                                     Height="16"
                                     Canvas.Left="5.34375"
                                     Canvas.Top="16.0313"
                                     Stretch="Fill"
                                     StrokeLineJoin="Round"
                                     Stroke="#FF000000"
                                     Fill="{Binding Strength, Converter={StaticResource colorConverter}, ConverterParameter=20}" />
                          <Path Width="6.88835"
                                Height="21.6562"
                                Canvas.Left="11.75"
                                Canvas.Top="10.375"
                                Stretch="Fill"
                                StrokeLineJoin="Round"
                                Stroke="#FF000000"
                                Fill="{Binding Strength, Converter={StaticResource colorConverter}, ConverterParameter=40}"
                                Data="F1 M 12.2768,10.875L 18.1384,10.875L 18.1115,31.5313L 12.25,31.5313L 12.2768,10.875 Z " />
                          <Rectangle Width="6.78126"
                                     Height="26.9687"
                                     Canvas.Left="18.5625"
                                     Canvas.Top="5.09376"
                                     Stretch="Fill"
                                     StrokeLineJoin="Round"
                                     Stroke="#FF000000"
                                     Fill="{Binding Strength, Converter={StaticResource colorConverter}, ConverterParameter=60}" />
                          <Rectangle Width="6.71874"
                                     Height="31.8437"
                                     Canvas.Left="25.2812"
                                     Canvas.Top="0.250002"
                                     Stretch="Fill"
                                     StrokeLineJoin="Round"
                                     Stroke="#FF000000"
                                     Fill="{Binding Strength, Converter={StaticResource colorConverter}, ConverterParameter=80}" />
                      </Canvas>
                  </DataTemplate>
              </ListBox.ItemTemplate>
          </ListBox>
      

      这样做的缺点是缺乏样式重用,这与提到的其他方法不同。

      【讨论】:

        猜你喜欢
        • 2011-10-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-22
        • 2013-12-13
        • 2012-07-31
        • 2018-10-25
        • 2010-11-28
        相关资源
        最近更新 更多