简体   繁体   English

c#wpf DataGrid:以编程方式更改绑定列上的图像源

[英]c# wpf DataGrid: programmatically changing image source on bound columns

I have a SQL Database with computers names bound to a DataGrid Like This: 我有一个SQL数据库,其中计算机名称绑定到DataGrid,如下所示:

                <Grid.Resources>
            <ResourceDictionary>
                <local:FileIconConverter2 x:Key="FileIconConverter2"/>
                <BitmapImage x:Key="Image-Unknown" UriSource="../Images/Status-Unknown.ico" />
                <BitmapImage x:Key="Image-Good" UriSource="../Images/Status-Good.ico" />
            </ResourceDictionary>
        </Grid.Resources>
    <DataGrid Name="datagrid1" AutoGenerateColumns="False" IsReadOnly="True" SelectionChanged="datagrid1_SelectionChanged">
<DataGrid.Columns>
    <DataGridTemplateColumn Header="Status" >
        <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <Image Source="{StaticResource Image-Unknown}"/>
            </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn>
    <DataGridTextColumn Header="Date d m yyyy" Binding="{Binding 'Date d m yyyy'}"/>
    <DataGridTextColumn Header="Device Name" Binding="{Binding DeviceName}"/>
    <DataGridTextColumn Header="OS" Binding="{Binding OS}"/>
    <DataGridTextColumn Header="OS" Binding="{Binding Model}"/>
    <DataGridTextColumn Header="EOL" Binding="{Binding DeviceAge}"/>
    <DataGridTextColumn Header="Location" Binding="{Binding Location}"/>
    <DataGridTextColumn Header="IP" Binding="{Binding IP}"/>
    <DataGridTextColumn Header="MAC" Binding="{Binding Mac}"/>
</DataGrid.Columns>

What I am trying to do is when you click on a row, have the status column image update to show if the computer is online by changing the image. 我想做的是当您单击一行时,通过更改图像来更新状态列图像以显示计算机是否在线。 The Status column is not in the database. “状态”列不在数据库中。 whenever I try changing the content of the status column I get [icon] or [bitmap] text, not an image, and if I scroll down then back up the image defaults back. 每当我尝试更改状态列的内容时,都会得到[icon]或[bitmap]文本,而不是图像,如果我向下滚动,则备份时图像默认返回。

Here is the Any Suggestions? 这是任何建议吗?

Edit: Where the table can contain 100's of entries, I only want to check the online status when a row is selected. 编辑:表可以包含100个条目的地方,我只想在选中一行时检查在线状态。 So I'm trying to use SelectionChanged event on datagrid1 like this: 所以我试图像这样在datagrid1上使用SelectionChanged事件:

    private void datagrid1_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        DataGrid dataGrid = sender as DataGrid;
        DataGridRow row = (DataGridRow)dataGrid.ItemContainerGenerator.ContainerFromIndex(dataGrid.SelectedIndex);
        DataGridCell rowColumn = dataGrid.Columns[2].GetCellContent(row).Parent as DataGridCell;
        string CellValue = ((TextBlock)rowColumn.Content).Text;
        log.Warn(CellValue);

        //myclass.GetCell(datagrid1, row.GetIndex(), 0).Content = Properties.Resources.Status_Good;
        myclass.GetCell(datagrid1, row.GetIndex(), 0).Content = (Bitmap)System.Drawing.Image.FromFile(@".\Images\Status-good.ico");

    }

The myClass.GetCell code comes from this post. myClass.GetCell代码来自这篇文章。

But, as you can see in this screen shot, I only get text and not the image. 但是,正如您在此屏幕快照中看到的那样,我只得到文本,而不是图像。 Screen Shot 屏幕截图

Did you try to add triggers to your image ? 您是否尝试向图像添加触发器?

<DataGridTemplateColumn Header="Status" >
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <Image >
               <Image.Style>
                   <Setter Property="Source" Value="{StaticResource Image-Unknown}"/>
                   <Style.Triggers>
                     <DataTrigger Binding="{Binding YourModelPropertyStatus}" Value="true">
                          <Setter Property="Source" Value="{StaticResource Image-Good}"/>
                     </DataTrigger>
                   </Style.Triggers>
               </Image.Style>
            </Image> 
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

Edit : 编辑:

Solution 1 (the closest to your existing code) 解决方案1(最接近您的现有代码)

Rather than searching and editing the cell content in code behind (which is really bad practice), use the arguments given by the selectionChanged callback like e.AddedItems and e.RemovedItems wich will give you the business models (representing your devices) wich have been added and removed. 与其在后面的代码中搜索和编辑单元格内容(这确实是一种错误做法), e.AddedItemse.RemovedItems的selectionChanged回调函数所提供的参数,这些参数将为您提供已经存在的业务模型(代表设备)。添加和删​​除。 Something like 就像是

        foreach (var addedItem in e.AddedItems)
        {
            var device = (Device) addedItem;
            device.CheckStatus();
        }
        foreach (var remItem in e.RemovedItems)
        {
            var device = (Device)remItem;
            device.SetToUnknown();
        }

Where CheckStatus is the method that check the online status and will set the flag YourModelPropertyStatus to true of false (and thus active the triggers described above) 其中CheckStatus是检查在线状态的方法,它将标志YourModelPropertyStatus设置为true或false(从而激活上述触发器)

Solution 2 (the cleanest way) 解决方案2(最干净的方法)

The best and cleanest way to acheive what you want, keeping the triggers solution in the XAML, is to manage everything on your view model using a CollectionView to wrapp your devices collection. 使触发器解决方案保持在XAML中的最佳,最简单的方法是使用CollectionView封装设备集合来管理视图模型中的所有内容。 In your XAML DataGrid set the IsSynchronizedToCurrentItem=true and then, in your view model, subscribe to CurrentChanged event and in the callback get the CurrentItem of the CollectionView and call the CheckStatus(); 在XAML DataGrid中,设置IsSynchronizedToCurrentItem=true ,然后在视图模型中,订阅CurrentChanged事件,然后在回调中获取CollectionView的CurrentItem并调用CheckStatus(); that can be either in your view model or in your device object. 可以在您的视图模型中,也可以在您的设备对象中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM