MVVM Binding popover isOpen in datagrid

时间:2017-11-21 10:37:15

标签: c# wpf mvvm popup

我有一个绑定到可观察集合的数据网格。我想在按钮上显示一个鼠标输入事件,显示从数据库中检索的一些内容。

为了提高效率,我想在鼠标悬停时获取这些数据,因此初始渲染速度更快。

我已将鼠标输入和鼠标离开事件绑定到ViewModel中的ICommand。这些控制台正确记录鼠标输入,鼠标离开行ID(为简洁起见省略了鼠标)

如果我手动输入isOpen =“true”,则所有弹出窗口都会按预期显示。

我遇到的问题是,如果我在命令委托中改变Observable集合,那么数据网格不会更新内容。 Observable集合在调试器中似乎是正确的。

//Conditions.cs
public class Condition
{
    public int Id { get; set; }
    public string Description { get; set; }
    public bool PopupOpen { get; set; }
    public string PopupContent { get; set; }
    …
}

视图模型

    private ObservableCollection<Condition> _conditionsObservableCollection;
    public ObservableCollection<Condition> ConditionsObservableCollection
    {
        get => _conditionsObservableCollection;
        set
        {
            _conditionsObservableCollection = value;
            DynamicOnPropertyChanged();
        }
    }

    private ICommand _showConditionChildrenMouseEnterCommand;
    public ICommand ShowConditionChildrenMouseEnterCommand=> _showConditionChildrenMouseEnterCommand ??
        (_showConditionChildrenMouseEnterCommand = new RelayCommand<int>(ShowConditionChildren));

    private void ShowConditionChildren(int id)
    {
        Console.WriteLine("enter:"+id); // this is output correctly.
        foreach (Condition condition in ConditionsObservableCollection)
        {
            condition.PopupOpen = condition.Id == id;
        }
        //ConditionsObservableCollection appears to be changed here.
        OnPropertyChanged("ConditionsObservableCollection");
    }

BaseViewModel

public event PropertyChangedEventHandler PropertyChanged;
public void DynamicOnPropertyChanged([CallerMemberName] string propertyName = null)
{
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));          
}

protected virtual void OnPropertyChanged(string propertyName)
{
    var handler = PropertyChanged;
    handler?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

DataGrid列

<DataGridTemplateColumn Header="Info">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <StackPanel>
                <Button Style="{StaticResource MaterialDesignFlatButton}">
                    <i:Interaction.Triggers>
                        <i:EventTrigger EventName="MouseEnter">
                            <i:InvokeCommandAction
                                CommandParameter="{Binding Path=Id}"
                                Command="{Binding Path=DataContext.ShowConditionChildrenMouseEnterCommand, RelativeSource={RelativeSource AncestorType=DataGrid}}"
                            />
                        </i:EventTrigger>
                        <i:EventTrigger EventName="MouseLeave">
                            <i:InvokeCommandAction
                                CommandParameter="{Binding Path=Id}"
                                Command="{Binding Path=DataContext.HideConditionChildrenMouseLeaveCommand, RelativeSource={RelativeSource AncestorType=DataGrid}}"
                            />
                        </i:EventTrigger>
                    </i:Interaction.Triggers>
                    <materialDesign:PackIcon Kind="InformationVariant"/>
                </Button>
                <Popup
                    HorizontalAlignment="Left"
                    VerticalAlignment="Bottom"
                    IsOpen="{Binding PopupOpen}">
                    <StackPanel Background="AntiqueWhite">
                        <TextBlock  Padding="5">Here is a popup for id: <Run Text="{Binding Id}"/></TextBlock>
                    </StackPanel>
                </Popup>
            </StackPanel>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

2 个答案:

答案 0 :(得分:0)

条件应该实现INotifyPropertyChanged ..

答案 1 :(得分:0)

public class Condition : INotifyPropertyChanged
{ 
    public void SetPropertyChanged(string propertyName)
    {
       PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
    public event PropertyChangedEventHandler PropertyChanged;
    public int Id { get; set; }
    public string Description { get; set; }
    private bool popUpOpen;
    public bool PopUpOpen
    {
        get { return popUpOpen; }
        set
        {
            popUpOpen = value;
            OnPropertyChanged("PopUpOpen");
        }
     }
    public string PopupContent { get; set; }
    …
}

您还需要在班级中实现INotifyPropertyChanged。您的viewmodel仅根据添加和删除的项目通知ObservableCollection项目的更改。如果要通知内部属性的更改,则必须执行此操作