WPF、Caliburn Micro 和 Dapper - Datagrid 复选框绑定

WPF, Caliburn Micro and Dapper - Datagrid Checkbox binding

我在一个 WPF 项目中使用 Caliburn Micro 和 Dapper,我在其中创建了一个 DataGrid,我用来自 SQL 服务器数据库 Table 的数据填充了它。请考虑以下代码片段:

ChangesModel.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PTSRDesktopUI.Models
{
    //public class for all changes attributes
    public class ChangesModel
    {
        public int ID { get; set; }
        public string Facility { get; set; }
        public string Controller { get; set; }
        public string ParameterName { get; set; }
        public string OldValue { get; set; }
        public string NewValue { get; set; }
        public DateTime ChangeDate { get; set; }
        public bool Validated { get; set; }
        public DateTime ValidationDate { get; set; }
    }
}

OverviewView.xaml

<!--Datagrid Table-->
<DataGrid Grid.Row="1" x:Name="Changes" CanUserAddRows="False" AutoGenerateColumns="False" HorizontalAlignment="Stretch">
    <DataGrid.Columns>
        <DataGridTextColumn CellStyle="{StaticResource DataGridCellCentered}" IsReadOnly="True" 
                            Header="Facility" Binding="{Binding Path=Facility}"/>
        <DataGridTextColumn CellStyle="{StaticResource DataGridCellCentered}" IsReadOnly="True" 
                            Header="Controller" Binding="{Binding Path=Controller}"/>
        <DataGridTextColumn CellStyle="{StaticResource DataGridCellCentered}" IsReadOnly="True" 
                            Header="Parameter" Binding="{Binding Path=ParameterName}"/>
        <DataGridTextColumn CellStyle="{StaticResource DataGridCellCentered}" IsReadOnly="True" 
                            Header="Old Value" Binding="{Binding Path=OldValue}"/>
        <DataGridTextColumn CellStyle="{StaticResource DataGridCellCentered}" IsReadOnly="True" 
                            Header="New Value" Binding="{Binding Path=NewValue}"/>
        <DataGridTextColumn CellStyle="{StaticResource DataGridCellCentered}" IsReadOnly="True" 
                            Header="Changed Date" Binding="{Binding Path=ChangeDate, 
                            StringFormat='{}{0:dd.MM HH:mm}'}"/>
        <DataGridTemplateColumn CellStyle="{StaticResource DataGridCellCentered}" 
                                Header="Validated" IsReadOnly="True">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate >
                    <CheckBox IsChecked="{Binding Path=Validated}" />
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTextColumn CellStyle="{StaticResource DataGridCellCentered}" IsReadOnly="True" 
                            Header="Validation Date" Binding="{Binding Path=ValidationDate, 
                            StringFormat='{}{0:dd.MM HH:mm}'}"/>
        <DataGridTemplateColumn CellStyle="{StaticResource DataGridCellCentered}" Header="Validate">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <Button x:Name="Validate_Btn" cal:Message.Attach="Validate">Validate</Button>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>

OverviewViewModel.cs

using Caliburn.Micro;
using PTSRDesktopUI.Helpers;
using PTSRDesktopUI.Models;

namespace PTSRDesktopUI.ViewModels
{
    public class OverviewViewModel : Screen
    {

        //Create new Bindable Collection variable of type ChangesModel
        public BindableCollection<ChangesModel> Changes { get; set; }


        public OverviewViewModel()
        {

            //Create connection to DataAccess class
            DataAccess db = new DataAccess();

            //get the changes from DataAccess function and store them as a bindable collection in Changes
            Changes = new BindableCollection<ChangesModel>(db.GetChanges());

        }

        //Validate_Btn click event
        public void Validate()
        {
           //Some Code        
        }

    }
}

DataAccess.cs

//Function to get all changes from database using stored procedures
public List<ChangesModel> GetChanges()
{
    using (IDbConnection connection = new System.Data.SqlClient.SqlConnection(DBHelper.CnnVal("ptsrDB")))
    {
        var output = connection.Query<ChangesModel>("dbo.getChanges").ToList();
        return output;
    }
}

我使用名为 getChanges 的存储过程从 SQL 服务器获取数据。显示数据,一切正常。我现在想做的是: 首先,我希望 Validate_Btn 仅在未选中 CheckBox 的行上可见。其次,如果用户单击 Validate_Btn,我想将 CheckBox 更改为已选中,使按钮不可见并使用 DataAccess class 中的存储过程触发新函数以更新数据库 table 中 Validated 的布尔值。有人知道我该怎么做吗?

要解决第一部分根据CheckBox是否勾选来显示和隐藏Button,你应该先在你的ChangesModel中实现INotifyPropertyChanged接口class 并在设置 Validated 属性 时引发 PropertyChanged 事件:

public class ChangesModel : INotifyPropertyChanged
{
    public int ID { get; set; }
    public string Facility { get; set; }
    public string Controller { get; set; }
    public string ParameterName { get; set; }
    public string OldValue { get; set; }
    public string NewValue { get; set; }
    public DateTime ChangeDate { get; set; }

    private bool _validated;
    public bool Validated
    {
        get { return _validated; }
        set { _validated = value; NotifyPropertyChanged(); }
    }

    public DateTime ValidationDate { get; set; }

    public event PropertyChangedEventHandler PropertyChanged; 
    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

}

然后您可以将 ButtonVisibility 属性 绑定到 Validated 源 属性 并使用转换器在 bool 值和一个 Visibility 枚举值:

<DataGridTemplateColumn Header="Validate">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <DataTemplate.Resources>
                <BooleanToVisibilityConverter x:Key="converter" />
            </DataTemplate.Resources>
            <Button x:Name="Validate_Btn" cal:Message.Attach="Validate"
                    Visibility="{Binding Validated, Converter={StaticResource converter}}">Validate</Button>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

您可能还想在 CheckBox 绑定上设置 UpdateSourcePropertyTrigger,以便立即设置源 属性:

<CheckBox IsChecked="{Binding Path=Validated, UpdateSourceTrigger=PropertyChanged}" />

为了在您单击按钮时调用您的 Validate(),您可以将 Bind.Model 附加 属性 绑定到视图模型:

<Button x:Name="Validate"
        cal:Bind.Model="{Binding DataContext, 
            RelativeSource={RelativeSource AncestorType=DataGrid}}">Validate</Button>

合并绑定需要指定 Visibility 绑定的来源:

<Button x:Name="Validate"
    Visibility="{Binding DataContext.Validated, 
       Converter={StaticResource converter}, RelativeSource={RelativeSource AncestorType=DataGridCell}}"
    cal:Bind.Model="{Binding DataContext, RelativeSource={RelativeSource AncestorType=DataGrid}}">Validate</Button>