Laden...

Forenbeiträge von torka Ingesamt 8 Beiträge

25.04.2020 - 00:56 Uhr

Genau so mache ich es doch - kam wohl anders rüber.

21.04.2020 - 21:34 Uhr

Meine Idee war, dass ich dann bei Programmstart und -ende die Devices besser als XML mit einem XMLSerializer laden bzw. speichern kann. Ist das ein sinnvolles Konzept?
Ich bin relativ unerfahren in der Richtung, hatte bisher nur schnell mal die ein oder andere C#-Applikation zusammengetippt, das hier ist mein erstes MVVM-Konzept.

21.04.2020 - 15:41 Uhr

Ich hab noch mal drüber nachgedacht und glaube, dass es vom Prinzip her richtig aufgebaut ist. Hier mal etwas ausführlicher die Struktur:

MainViewModel.cs


    public class MainViewModel : ViewModelBase
    {
        private readonly ICommandManager _commandManager;
        private readonly IMessageService _messageService;
        private readonly ISensorsService _sensorsService;
        private readonly IUIVisualizerService _uiVisualizerService;
        public MainViewModel(ICommandManager commandManager, IMessageService messageService, ISensorsService sensorsService, IUIVisualizerService uiVisualizerService)
        {
            // Services
            Argument.IsNotNull(() => commandManager);
            _commandManager = commandManager;
            Argument.IsNotNull(() => sensorsService);
            _sensorsService = sensorsService; 
            Argument.IsNotNull(() => uiVisualizerService);
            _uiVisualizerService = uiVisualizerService;
            Argument.IsNotNull(() => messageService);
            _messageService = messageService;
            // Commands            
           }       
        public ObservableCollection<Models.Device> Devices
        {
            get { return GetValue<ObservableCollection<Models.Device>>(DevicesProperty); }
            set { SetValue(DevicesProperty, value); }
        }
        public static readonly PropertyData DevicesProperty = RegisterProperty(nameof(Sensors), typeof(ObservableCollection<Models.Device>), null);

MainView.xaml


   <Grid>
        <avalonDock:DockingManager Name="dockingManager" Loaded="OnDockManagerLoaded">
            <avalonDock:LayoutRoot>
                <avalonDock:LayoutPanel Orientation="Horizontal" CanRepositionItems="False">
                    <avalonDock:LayoutAnchorablePane DockMinWidth="500" 
                                                        DockWidth="500" 
                                                        CanRepositionItems="False" >
                        <avalonDock:LayoutAnchorable x:Name="dockDevices" 
                                                        Title="Geräte" 
                                                        AutoHideMinHeight="500"
                                                        AutoHideMinWidth="495"
                                                        CanClose="False" 
                                                        CanDockAsTabbedDocument="False" 
                                                        CanFloat="False" 
                                                        CanHide="False">
                            <ScrollViewer VerticalScrollBarVisibility="Visible">
                                <ItemsControl ItemsSource="{Binding Devices}"  Width="460">
                                    <ItemsControl.ItemTemplate>
                                        <DataTemplate>
                                            <local:Device Margin="5"/>
                                        </DataTemplate>
                                    </ItemsControl.ItemTemplate>
                                </ItemsControl>
                            </ScrollViewer>
                        </avalonDock:LayoutAnchorable>
                    </avalonDock:LayoutAnchorablePane>
                    <avalonDock:LayoutDocumentPane ShowHeader="False">
                        <avalonDock:LayoutDocument CanClose="False"
                                                    CanFloat="False"
                                                    IsMaximized="True">
                            <!-- Hier kommen dann weitere control-ViewModels für die Geräte rein-->
                        </avalonDock:LayoutDocument>
                    </avalonDock:LayoutDocumentPane>
                </avalonDock:LayoutPanel>
            </avalonDock:LayoutRoot>
        </avalonDock:DockingManager>
    </Grid>

Device.xaml


<Grid>
	<Border BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Left" Height="233" VerticalAlignment="Top" Width="450" CornerRadius="10" Background="Transparent">
		<Grid x:Name="deviceGrid" Background="Transparent">			
			<Border x:Name="topBorder" Background="{StaticResource CiDarkGrey}" CornerRadius="10,10,0,0">
				<Grid>
					<Grid.ColumnDefinitions>
						<ColumnDefinition Width="*"/>
						<ColumnDefinition Width="30"/>
					</Grid.ColumnDefinitions>
					<TextBlock Grid.Column="0" Foreground="White"
						   HorizontalAlignment="Center"
						   VerticalAlignment="Top"                          
						   Height="25">
						<!-- Header row text -->
						<Run Text="Device: Serial Number"/>
						<Run Text="{Binding SerialNumber}"/>
						<Run Text=" - ("/>
						<Run Text="{Binding Path=IP, Converter={StaticResource IpAddressToString}}"/>
						<Run Text=")"/>
					</TextBlock>
					<!-- Close Button-->
					<Button Grid.Column="1" Margin="-15,-15"  Width="20" Height="20"  Background="{StaticResource CiLightGrey}" Command="{Binding RemoveDevice}">
						<TextBlock FontWeight="UltraBold" Text="&#xE106;" FontFamily="Segoe MDL2 Assets" FontSize="10" />
						<Button.Resources>
							<Style TargetType="Border">
								<Setter Property="CornerRadius" Value="10"/>
							</Style>
						</Button.Resources>
					</Button>
				</Grid>
			</Border>
		</Grid>
	</Border>
</Grid>

DeviceViewModel.cs


public class DeviceViewModel : ViewModelBase
{
	#region Public Properties
	/// <summary>
	/// device serial number
	/// </summary>
	public String SerialNumber { get; set; }
	/// <summary>
	/// device IP
	/// </summary>
	public String IP { get; set; }
	#endregion
	#region Commands
	/// <summary>
	/// Remove device
	/// </summary>
	public ICommand RemoveDevice { get; set; }
	#endregion
	#region Constructor
	public DeviceViewModel()
	{            
		RemoveDevice = new TaskCommand(RemoveDevice);
	}

	private async Task RemoveDevice)
	{
		System.Windows.Forms.MessageBox.Show("RemoveDevice aufgerufen");
	}
 }

Der RemoveDevice command wird aufgerufen, das binding funktioniert in dieser Richtung. Was mir (und meinem Verständnis noch) fehlt ist das Binding auf die Eigenschaften aus der ObesservableCollection, die im MainViewModel steckt. Es ist auf jeden Fall schon mal so, dass mir in meiner ItemsControl zwei Device-Views angezeigt werden, wenn die OC auch zwei Einträge hat. Was schief läuft ist wohl das binding. Bin ich da auf nem Holzweg?

21.04.2020 - 13:30 Uhr

Ja, es ist ein View. Das ViewModel heißt DeviceViewModel, die View' Device' (vorher Gerät). Aber ist denn mein Ansatz mit der ObservableCollection richtig?

21.04.2020 - 12:22 Uhr

Mein Model Gerät ist eine Klasse, die von der Klasse ModelBase (ich verwende catel) erbt. Da hab ich Eigenschaften des Gerätes drin, bspw.


    public class Gerät : ModelBase
    {
        #region Properties
        /// <summary>
        /// IP-Address of the device
        /// </summary>
        public IPAddress IP
        {
            get { return GetValue<IPAddress>(IPProperty); }
            set { SetValue(IPProperty, value); }
        }
        public static readonly PropertyData IPProperty = RegisterProperty(nameof(IP), typeof(IPAddress), null);

Der Typ aus der ObservableCollection<Gerät> ist das Model, also ObservableCollection<Models.Gerät>, das Control das in dem DataTemplate steckt ist ein Viewmodel mit ebenfalls dem Namen "Gerät". Dort hab ich Commands die im ViewModel Gerät drin stehen und bei Tastendruck ausgeführt werden. Ich verstehe nur nicht, wie ich jetzt Daten aus dem Model in das Viewmodel bekomme. Wo ist mein Denkfehler?

Was ich eigentlich wollte:
Eine ObservableCollection die ich schön speichern kann, organisiert in den Models (das sollte doch eigentlich richtig so sein) und ein ViewModel, welches sich an den Objekten in der Collection bedient und die Eigenschaften darstellt.

21.04.2020 - 10:19 Uhr

Mein Ziel ist, eine Liste von ViewModels in meiner MainView in einem Dock zu erzeugen, die physischen Netzwerkgeräten folgt. Jedes Gerät soll dynamisch sein ViewModel bekommen, das ViewModel soll in der Lage sein, Funktionen auf dem betreffenden Viewmodel für ein Gerät auszuführen. Um die Eigenschaften eines Gerätes zu organisieren habe ich ein Model erstellt, mit Eigenschaften wie IP, Verbindung, etc.
In meinem MainViewModel baue ich dann die ObservableCollection<Gerät> Geräte und binde dann in das XAML die Collection wie folgt:

  
<Grid>
        <avalonDock:DockingManager Name="dockingManager" Loaded="OnDockManagerLoaded">
            <avalonDock:LayoutRoot>
                <avalonDock:LayoutPanel Orientation="Horizontal" CanRepositionItems="False">
                    <avalonDock:LayoutAnchorablePane DockMinWidth="500" 
                                                        DockWidth="500" 
                                                        CanRepositionItems="False" >
                        <avalonDock:LayoutAnchorable x:Name="dockGeräte" 
                                                        Title="Geräte" 
                                                        AutoHideMinHeight="500"
                                                        AutoHideMinWidth="495"
                                                        CanClose="False" 
                                                        CanDockAsTabbedDocument="False" 
                                                        CanFloat="False" 
                                                        CanHide="False">
                            <ScrollViewer VerticalScrollBarVisibility="Visible">
                                <ItemsControl ItemsSource="{Binding Geräte}"  Width="460">
                                    <ItemsControl.ItemTemplate>
                                        <DataTemplate>
                                            <local:Gerät Margin="5"/>
                                        </DataTemplate>
                                    </ItemsControl.ItemTemplate>
                                </ItemsControl>
                            </ScrollViewer>
                        </avalonDock:LayoutAnchorable>
                    </avalonDock:LayoutAnchorablePane>
                    <avalonDock:LayoutDocumentPane ShowHeader="False">
                        <avalonDock:LayoutDocument CanClose="False"
                                                    CanFloat="False"
                                                    IsMaximized="True">
                            <!-- Hier kommen dann weitere (auswählbare) control-ViewModels für die Geräte rein, welche aus dem Ribbon für ein ausgewähltes Gerät bestimmte Funktionen ausführen (bspw. Kommunikation aneigen) -->
                        </avalonDock:LayoutDocument>
                    </avalonDock:LayoutDocumentPane>
                </avalonDock:LayoutPanel>
            </avalonDock:LayoutRoot>
        </avalonDock:DockingManager>
    </Grid>

Gebundene Funktionen auf die ViewModels der Geräte funktionieren, ich kann jedoch nicht die Eigenschaften des Models abrufen, dessen Button auf dem ViewModel geklickt wurde.

Ich hoffe, das war etwas verständlicher, vielen Dank schon mal für Eure Antworten.

20.04.2020 - 18:21 Uhr

Hallo,

ich versuche gerade eine Applikation zu bauen, in der aus einer ObservableCollection von Models dynamisch per ItemsContol template die zugehörigen ViewModels geladen werden. Das binding der Daten aus den Objekten der ObservableCollection zum XAML funktioniert soweit, die richtigen Einträge werden dargestellt. Was mir jedoch nicht gelingt ist das Ausführen von Methoden auf dem Objekt des zugehörigen ViewModels, bspw. wenn man einen Button in einem VM klickt.
Ich hoffe ich konnte mein Problem ausreichend beschreiben sowie, dass jemand mir helfen kann, per google/Forensuche hatte ich keinen Erfolg - vielleicht sind es auch die falschen Begriffe

Gruß