这个问题的变化似乎是相当普遍的,但我还没有找到一个适合我的解决方案。我试图在Button.ContextMenu中使用Observable集合放置下拉菜单,并且认为我处于正确的轨道上,缺少一件:我还没有能够获得所选项目的索引,尽管我可以在调试器中看到我的集合,我开始怀疑这些项目是否真的被找到,并会在我去的时候解释。首先,XAML ...你可以看到我有一个Button内容的绑定,并且这个想法是在菜单项被选中后,我的代码将会更新这个属性。它可以,如果我能得到正采集收集的指标:正确绑定下拉菜单从ObservableCollection并获得其索引
<Button x:Name="DeviceSelMenuButton" Content="{Binding DeviceID_and_SN, Mode=TwoWay}" HorizontalAlignment="Left" Height="28" Margin="25,103,0,0" VerticalAlignment="Top" Width="187" FontSize="14" Click="DeviceSelMenuButton_Click">
<Button.ContextMenu>
<ContextMenu ItemsSource="{Binding DeviceID_SN_Collection, Mode=TwoWay}">
<ContextMenu.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="IsCheckable" Value="true"/>
<Setter Property="Command" Value="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Button}}, Path=DataContext.MyCommand}"/>
<Setter Property="CommandParameter" Value="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ContextMenu}}}"/>
</Style>
</ContextMenu.ItemContainerStyle>
</ContextMenu>
</Button.ContextMenu>
</Button>
正如你可以想像,我已经尝试了许多变化对于CommandParameter绑定,但是这一个我至少可以看到一些我的ICommand方法中的东西。麻烦我的事情是,在第一次按下按钮(并且在输出窗口中没有关于绑定的错误)时,在ContextMenu cm的Items属性下,我看到items.CurrentItem下的合法项目标签和item当前位置是0--最初看起来很有希望,希望我可以用它作为索引,直到我意识到我正在查看最后一个项目,所以它一定是没有意义的。之后,第二次以及随后按下按钮时,items.CurrentItem为null,items.Current位置为0xffffffff。粘贴在代码中的相关片段,先从类定义集合,ICommand的,等:
class CustomDeviceGUI : INotifyPropertyChanged
{
// Declare the event
public event PropertyChangedEventHandler PropertyChanged = delegate { };
private string _deviceDisplayString;
private ICommand UpdateMenuICommand;
List<string> ControllerDeviceList = new List<string>();
private System.Collections.ObjectModel.ObservableCollection<string> _DeviceID_SN_Collection = new System.Collections.ObjectModel.ObservableCollection<string>();
// CTOR
public CustomDeviceGUI()
{
ControllerDeviceList.Add("CustomDevice Device 1");
ControllerDeviceList.Add("CustomDevice Device 2");
ControllerDeviceList.Add("CustomDevice Device 3");
ControllerDeviceList.Add("CustomDevice Device 6");
UpdateDeviceID(3); // TODO Get from GUI!!!
}
#region CustomDeviceGUI Properties
public System.Collections.ObjectModel.ObservableCollection<string> DeviceID_SN_Collection
{
get
{
_DeviceID_SN_Collection.Clear();
foreach (string str in ControllerDeviceList)
{
_DeviceID_SN_Collection.Add(str);
}
return _DeviceID_SN_Collection;
}
private set
{
_DeviceID_SN_Collection = value;
}
}
public string DeviceID_and_SN
{
get
{
return _deviceDisplayString;
}
private set
{
_deviceDisplayString = value;
}
}
public ICommand MyCommand
{
get
{
if (UpdateMenuICommand == null)
UpdateMenuICommand = new MyGuiCommand();
return UpdateMenuICommand;
}
set
{
UpdateMenuICommand = value;
RaisePropertyChangeEvent("MyCommand"); // ????
}
}
public void UpdateDeviceID(int deviceID)
{
this._deviceDisplayString = ControllerDeviceList[deviceID];
RaisePropertyChangeEvent("DeviceID_and_SN");
RaisePropertyChangeEvent("DeviceID_SN_Collection");
}
public class MyGuiCommand : ICommand
{
// Two events are kicked off when the command is executed
public static event UpdateDeviceSelectedEventHandler UpdateDeviceSelectedEvent;
// defining signature for any event handlers for the events we create here
public delegate void UpdateDeviceSelectedEventHandler(int deviceIndex);
public void Execute(object parameter)
{
ContextMenu cm = (ContextMenu)parameter;
var itemSource = cm.ItemsSource;
var itemBG = cm.ItemBindingGroup;
var items = cm.Items;
UpdateDeviceSelectedEvent(1); // TODO parameter with index from GUI
}
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged // was ;
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
}
} // class CustomDeviceGUI
终于从MainWindow.xaml.cs相关的代码,而不是很多发生在这里:
// register for the event from the ICommand.Execute
WpfBindingAttempts.CustomDeviceGUI.MyGuiCommand.UpdateDeviceSelectedEvent += new WpfBindingAttempts.CustomDeviceGUI.MyGuiCommand.UpdateDeviceSelectedEventHandler(UpdateDeviceSelectedAfterSwitch);
// Handles event that occurs when a different device is selected
// via the dropdown menu -- sets the active device, and updates its ID/SN
void UpdateDeviceSelectedAfterSwitch(int deviceIndex)
{
_customDeviceGui.UpdateDeviceID(deviceIndex);
}
代码背后按钮:
private void DeviceSelMenuButton_Click(object sender, RoutedEventArgs e)
{
// " (sender as Button)" is PlacementTarget
(sender as Button).ContextMenu.IsEnabled = true;
(sender as Button).ContextMenu.PlacementTarget = (sender as Button);
(sender as Button).ContextMenu.Placement = System.Windows.Controls.Primitives.PlacementMode.Bottom;
(sender as Button).ContextMenu.IsOpen = true;
}
认为这一切。任何帮助是极大的赞赏。如果这看起来很熟悉,那就是。我克服了第一个障碍,撞上了这堵砖墙。
谢谢你,谢谢你,指出明显的我! – Stephen