Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF - MVVM - Return Bindable Control Template from View Model

Tags:

c#

mvvm

wpf

I'm trying to display available Wifi networks (using ManagedWifi SDK) on a listview.

I have defined ObservableCollection of WifiNetwork (contains name, type, signal Strength(int) etc) in my viewmodel as shown below

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

I have defined Control templates (like 1 green bar and 4 white bars to indicate signal strength <= 20%, 2 green bars and 3 white bars to indicate signal strength between 20 to 40% etc) in Application Resources in app.xaml as shown below

<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>

Now I need to return this control template from my view model to bind it to a button to show the appropriate signal strength in my listBox.

I probably need to have some kind of conversion from Signal Strength (int) to Control template.

Any suggestions / code examples to achieve this task?

like image 219
Bradman Avatar asked Jan 28 '26 00:01

Bradman


2 Answers

This should guide to right direction:

    <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>
like image 126
Dariusz Wickowski Avatar answered Jan 30 '26 16:01

Dariusz Wickowski


I like Darek's answer, but if you really want to use control templates like this, you should use a style and a data trigger bound to the signal strength, e.g.:

<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>
like image 36
Robert Rossney Avatar answered Jan 30 '26 16:01

Robert Rossney