C# WPF MVVM ListViewItem的ContextMenu的MenuItem中Command绑定的CommandBase事件无响应。
创建了一个MainWindow,在MainWindow中间划定一块区域用以绑定显示其他的View界面;
我在一个View(MonitorView)中创了一个ListView,每一个Items都有几个操作,我将这几个操作定义在了ContextMenu中,当鼠标右击时就显示ContextMenu,点击MenuItem执行对应的操作;
<!-- ContextMenu -->>
<ContextMenu x:Key="ContextMenu1">
<MenuItem Header="出厂" FontSize="14" >
<MenuItem Header="下行" FontSize="14" Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl},Path=DataContext.DownOutTrainCommand}"
CommandParameter="{Binding}"/>
<Separator/>
<MenuItem Header="上行" FontSize="14"/>
</MenuItem>
<Separator/>
<MenuItem Header="去15" FontSize="14" Command="{Binding DataContext.DownOutTrainCommand,RelativeSource={RelativeSource AncestorType={x:Type local:MonitorView}}}"
CommandParameter="{Binding }"/>
<MenuItem Header="去14" FontSize="14" Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl},Path=DataContext.DownOutTrainCommand}"
CommandParameter="{Binding}" />
<MenuItem Header="去13" FontSize="14" Command="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.DownOutTrainCommand}"
CommandParameter="{Binding}" />
</ContextMenu>
ListViewItem 的 ItemContainerStyle的样式
<Style x:Key="ListItemType" TargetType="{x:Type ListViewItem}">
<Setter Property="Margin" Value="2,10,2,0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border BorderThickness="1" CornerRadius="5" x:Name="borderground" >
<Border.Background>
<ImageBrush ImageSource="pack://application:,,,/huainan_railway;component/Assets/Image/train.png" Stretch="UniformToFill"/>
</Border.Background>
<Border.Effect>
<DropShadowEffect Color="#FF1F0F0B" BlurRadius="10" Opacity="0.5"></DropShadowEffect>
</Border.Effect>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="4*"/>
</Grid.RowDefinitions>
<Border Grid.Row="0" Background="#2c6cf3" Width="18" Height="18" CornerRadius="9" Margin="2,0,3,-7" BorderBrush="White" BorderThickness="1" HorizontalAlignment="Left">
<TextBlock Text="{Binding StockIndex}" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="16" Foreground="White"/>
</Border>
<Border Grid.Row="1" Margin="5,0" Background="Transparent" Name="root" BorderThickness="0,0,0,1" CornerRadius="6">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding MachineType}" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="16" Foreground="#FF17FF00" FontWeight="Bold"/>
<TextBlock Grid.Column="1" Text="{Binding TrainNumber}" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="16" Foreground="#FF17FF00" FontWeight="Bold"/>
</Grid>
</Border>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="ContextMenu" Value="{StaticResource ContextMenu1}"/>
<Setter Property="ToolTip" Value="{Binding Source={StaticResource ItempInfoTip}}"/>
</Style>
ListView 调用
<ListView ItemsSource="{Binding trainsSolid.trains5}" Background="Transparent"
BorderThickness="1,1,1,1" Style="{StaticResource ListBorderBrush}"
ItemContainerStyle="{StaticResource ListItemType}"
Height="55" Width="461" Canvas.Top="610" Canvas.Left="743">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
ViewModel中的事件
//出车 下行
private CommandBase _downOutTrainCommand;
public CommandBase DownOutTrainCommand
{
get
{
if (_downOutTrainCommand == null)
{
_downOutTrainCommand = new CommandBase();
_downOutTrainCommand.DoExecute = new Action<object>(obj =>
{
try
{
TrainModel trainModel = (TrainModel)obj;
//TrainPlanModel trainPlanModel = (TrainPlanModel)obj;
//monitorService.UpdatePlanState(3, trainPlanModel.ID);
//trainPlanModel.Status = 3;
//ObservableCollection<TrainModel> tM = trainsSolid.GetObservable(trainPlanModel.Stock);
//monitorService.insertTrain(trainPlanModel, tM);
Initialize();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
});
}
return _downOutTrainCommand;
}
}
要明确指定数据源 无法通过继承拿到? 但是不知道怎么写;加载ViewModel? 尝试了不行,不知道怎么回事;
<<ResourceDictionary >
<vm:MonitorViewModel x:Key="mvm"/>
</ResourceDictionary>
<UserControl.DataContext>
<Binding Source="{StaticResource mvm}"/>
</UserControl.DataContext>
<UserControl.ContextMenu>
<ContextMenu DataContext="{StaticResource mvm}"/>
</UserControl.ContextMenu>
【以下回答由 ChatGPT 生成】
我很抱歉,但是你没有给出具体的问题。请提供问题后,我将尽力给出相应的解决方案。
你的DataContext有没有正确地绑定到你的ViewModel上
WPF MVVM模式开发中列表控件内的按钮触发不了command事件
可以参考下
根据你提供的信息,我可以给你以下建议:
确认你的CommandBase事件是否正确绑定到了MenuItem上。可以通过在MenuItem上打断点或者输出日志来确认Command被触发与否。
确认你的CommandBase事件是否正确实现,是否有误导致无法被正确触发。
确认ContextMenu的样式或者模板是否被修改,可能会导致ContextMenu无法正确显示或者Command无法触发。
如果以上都没有问题,可以尝试在ListViewItem上绑定MouseDown或者PreviewMouseDown事件,然后在事件处理中手动打开ContextMenu,再通过CommandParameter传递ListViewItem对应的数据模型。
如果还有问题,可以考虑提供更详细的代码或者项目结构,方便进行更深入的分析和解决。
事件没有正确绑定
检查一下事件绑定
逻辑回归是一种二分类算法,用于预测二分类问题。逻辑回归的优点是计算速度快,便于理解和实现。本文将介绍使用 Python 构建逻辑回归模型,进行5折交叉验证,每验证一次绘制一条曲线,并最终绘制一条平均 ROC 曲线。
本文使用的数据集是 UCI 的 Pima Indians Diabetes 数据集,该数据集包含了768个样本,8个特征和1个二元分类。我们将使用该数据集来构建逻辑回归模型。
首先,我们需要导入sklearn
和pandas
库,并读取数据集:
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import roc_curve, auc
import numpy as np
import matplotlib.pyplot as plt
# 加载数据集
data = pd.read_csv('diabetes.csv')
# 划分数据集
X = data.iloc[:, :-1].values
y = data.iloc[:, -1].values
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=42)
我们将数据集划分为训练集和测试集,测试集占25%。
我们将使用LogisticRegression
类来构建逻辑回归模型。首先,我们需要实例化该类,并将训练集数据拟合到模型中:
# 构建逻辑回归模型
logreg = LogisticRegression()
# 将训练集拟合到模型中
logreg.fit(X_train, y_train)
接下来,我们使用cross_val_predict
函数来进行5折交叉验证,并使用roc_curve
函数来计算 ROC 曲线的参数。
from sklearn.model_selection import cross_val_predict
# 进行5折交叉验证
y_score = cross_val_predict(logreg, X_train, y_train, cv=5, method='predict_proba')
# 计算 ROC 曲线的参数
fpr, tpr, thresholds = roc_curve(y_train, y_score[:, 1])
roc_auc = auc(fpr, tpr)
# 绘制 ROC 曲线
plt.plot(fpr, tpr, label='ROC curve (area = %0.2f)' % roc_auc)
# 绘制对角线
plt.plot([0, 1], [0, 1], 'k--')
# 设置图形参数
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver operating characteristic')
plt.legend(loc='lower right')
plt.show()
我们使用cross_val_predict
函数进行5折交叉验证,并将预测的概率值存储在y_score
中。然后,我们使用roc_curve
函数来计算 ROC 曲线的参数,包括真阳性率和假阳性率。最后,我们使用plt.plot
函数将 ROC 曲线绘制出来。
接下来,我们使用for
循环进行5次交叉验证,并绘制5条 ROC 曲线:
from sklearn.model_selection import StratifiedKFold
# 进行5折交叉验证
cv = StratifiedKFold(n_splits=5)
mean_tpr = 0.0
mean_fpr = np.linspace(0, 1, 100)
colors = ['blue', 'red', 'green', 'purple', 'black']
# 绘制多条 ROC 曲线
for i, (train, test) in enumerate(cv.split(X_train, y_train)):
probas_ = logreg.fit(X_train[train], y_train[train]).predict_proba(X_train[test])
fpr, tpr, thresholds = roc_curve(y_train[test], probas_[:, 1])
mean_tpr += np.interp(mean_fpr, fpr, tpr)
plt.plot(fpr, tpr, lw=1, color=colors[i],
label='ROC fold %d (area = %0.2f)' % (i, auc(fpr, tpr)))
# 绘制随机猜测的对角线
plt.plot([0, 1], [0, 1], linestyle='--', lw=2, color='black',
label='Random guess', alpha=.8)
# 计算和绘制平均 ROC 曲线
mean_tpr /= cv.get_n_splits(X_train, y_train)
mean_tpr[-1] = 1.0
mean_auc = auc(mean_fpr, mean_tpr)
plt.plot(mean_fpr, mean_tpr, color='navy',
label='Mean ROC (area = %0.2f)' % mean_auc, lw=2)
# 设置图形参数
plt.xlim([-0.05, 1.05])
plt.ylim([-0.05, 1.05])
plt.xlabel('False Positive Rate', fontsize=16)
plt.ylabel('True Positive Rate', fontsize=16)
plt.title('Receiver Operating Characteristic (ROC) Curve', fontsize=18)
plt.legend(loc="lower right", fontsize=14)
plt.show()
在for
循环中,我们使用StratifiedKFold
函数进行5折交叉验证,并在每次交叉验证中计算 ROC 曲线的参数。我们使用np.interp
函数将所有曲线插值到相同的假阳性率上,然后将真阳性率相加,计算平均值。最后,我们绘制平均 ROC 曲线。
在本文中,我们使用 Python 构建了一个逻辑回归模型,并进行了5折交叉验证。我们绘制了5条 ROC 曲线,并计算了平均 ROC 曲线。通过绘制 ROC 曲线,我们可以评估模型的性能,并选择最佳的阈值来进行分类。
如果你在ListView中使用了一些自定义的视图或模板,那么需要将这些视图或模板的点击事件与ContextMenu的点击事件解耦。这样,点击事件就不会互相干扰。
其次,检查是否有其他的事件处理器阻止了右键菜单的触发。例如,某些鼠标事件处理器可能会阻止右键菜单的弹出。