我有一个数据网格。我想添加制表符时,行双击事件上升。当AddTab方法被调用时,Tab被添加到ObservableCollection,但它不显示在TabControl上。为什么它没有出现?因为有一个错误的DataContext当方法调用?
<DataGrid helpers:RowDoubleClickHandler.MethodName="AddTab" AutoGenerateColumns="False"
IsSynchronizedWithCurrentItem="True" CanUserResizeRows="True" x:Name="dataGrid1"
ItemsSource="{Binding DataGridEntries3}" HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch" IsReadOnly="True">
ViewModel中的AddTab方法
public void AddTab()
{
Tabs.Add(new TabEntry
{
Description = "Tab3",
DataGridEntries = new ObservableCollection<DataGridEntry>()
{
new DataGridEntry()
{
}
}
});
XAML with TabControl
<Window x:Class="ProjectZero.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:ProjectZero"
Title="MainWindow" Height="350" Width="525" DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Window.Resources>
<vm:MainViewModel x:Key="ViewModel"/>
</Window.Resources>
<Grid>
<ToolBar Height="40" VerticalAlignment="Top">
<Menu>
<MenuItem Header="Menu" Margin="6" Foreground="White" FontSize="14" FontFamily="Times New Roman">
<MenuItem Header="Add Invoice" Command="{Binding AddInvoice}"/>
<MenuItem Header="Invoices List" Command="{Binding AddInvoiceList}" FontFamily="Tahoma" />
</MenuItem>
<Menu.Background>
<SolidColorBrush />
</Menu.Background>
</Menu>
<ToolBar.Background>
<LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
<GradientStop Color="Black" Offset="0" />
<GradientStop Color="#FF173ADE" Offset="0.431" />
<GradientStop Color="#FF0B1D6F" Offset="0.646" />
</LinearGradientBrush>
</ToolBar.Background>
</ToolBar>
<TabControl x:Name="tabControl1" SelectedItem="{Binding SelectedItem}" ItemsSource="{Binding Tabs}" ItemTemplate="{DynamicResource DataTemplateType1}" TabStripPlacement="Top" HorizontalAlignment="Stretch" Margin="10,46,0,0" VerticalAlignment="Stretch" Width="Auto">
</TabControl>
ViewModel for Tabs
public class MainViewModel : BaseViewModel
{
public RelayCommand RelayCommand { get; set; }
public MainViewModel()
{
this.RelayCommand = new RelayCommand(this);
Tabs.CollectionChanged += (o, e) =>
{
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
{
foreach (BaseViewModel item in e.NewItems)
if (item.MyType == "TabEntry")
DataGridEntries3.Add(item as TabEntry);
}
};
var t = (from i in Tabs where i.MyType == "TabEntry" select (TabEntry)i);
DataGridEntries3 = new ObservableCollection<TabEntry>(t);
}
private ObservableCollection<BaseViewModel> _tabs;
public ObservableCollection<BaseViewModel> Tabs
{
get { return _tabs != null ? _tabs : _tabs = new ObservableCollection<BaseViewModel>(); }
set { _tabs = value; OnPropertyChanged("Tabs"); }
}
BaseViewModel _SelectedItem;
public BaseViewModel SelectedItem
{
get { return _SelectedItem; }
set { _SelectedItem = value; OnPropertyChanged("SelectedItem"); }
}
private ObservableCollection<TabEntry> _DataGridEntries3;
public ObservableCollection<TabEntry> DataGridEntries3
{
get { return _DataGridEntries3 != null ? _DataGridEntries3 : _DataGridEntries3 = new ObservableCollection<TabEntry>(); }
set { _DataGridEntries3 = value; OnPropertyChanged("DataGridEntries3"); }
}
ICommand _AddInvoice = null;
ICommand _AddInvoiceList = null;
public ICommand AddInvoice
{
get
{
return _AddInvoice != null ? _AddInvoice : _AddInvoice.SetCommand(param =>
{
Tabs.Add(new TabEntry
{
Description = "Tab3",
DataGridEntries = new ObservableCollection<DataGridEntry>()
{
new DataGridEntry()
{
}
}
});
});
}
}
public ICommand AddInvoiceList
{
get
{
return _AddInvoiceList != null ? _AddInvoiceList : _AddInvoiceList.SetCommand(param =>
{
var tab_dc = Tabs.FirstOrDefault(it => it.GetType() == typeof(MainViewModel));
if (tab_dc != null)
{
Tabs.Add(tab_dc);
}
else
{
var new_tab = new MainViewModel();
Tabs.Add(new_tab);
}
});
}
}
}
还有RowDoubleClick事件处理程序
public sealed class RowDoubleClickHandler : FrameworkElement
{
public RowDoubleClickHandler(DataGrid dataGrid)
{
MouseButtonEventHandler handler = (sender, args) =>
{
var row = sender as DataGridRow;
if (row != null && row.IsSelected)
{
var methodName = GetMethodName(dataGrid);
var dataContextType = dataGrid.DataContext.GetType();
var method = dataContextType.GetMethod(methodName);
if (method == null)
{
throw new MissingMethodException(methodName);
}
method.Invoke(dataGrid.DataContext, null);
}
};
dataGrid.LoadingRow += (s, e) =>
{
e.Row.MouseDoubleClick += handler;
};
dataGrid.UnloadingRow += (s, e) =>
{
e.Row.MouseDoubleClick -= handler;
};
}
public static string GetMethodName(DataGrid dataGrid)
{
return (string)dataGrid.GetValue(MethodNameProperty);
}
public static void SetMethodName(DataGrid dataGrid, string value)
{
dataGrid.SetValue(MethodNameProperty, value);
}
public static readonly DependencyProperty MethodNameProperty = DependencyProperty.RegisterAttached(
"MethodName",
typeof(string),
typeof(RowDoubleClickHandler),
new PropertyMetadata((o, e) =>
{
var dataGrid = o as DataGrid;
if (dataGrid != null)
{
new RowDoubleClickHandler(dataGrid);
}
}));
}
鉴于您在评论中提出的问题,以下是一些建议:
:
private ObservableCollection<BaseViewModel> _tabs;
public ObservableCollection<BaseViewModel> Tabs
{
get { return _tabs != null ? _tabs : _tabs = new ObservableCollection<BaseViewModel>(); }
set { _tabs = value; OnPropertyChanged("Tabs"); }
}
可以重写为:
public ObservableCollection<BaseViewModel> Tabs { get; private set; }
添加到构造函数中:
Tabs = new ObservableCollection<BaseViewModel>();
在您的代码中这是一个一致的主题。基本上,不要修改你的属性getter/setter,除非你真的真的需要。而在你的情况下,它所做的只是使事情复杂化。
当你有一个getter,它会在第一次调用时向你的选项卡集合中添加一个选项卡时,这尤其令人困惑。这在编程上很难理解。只要像其他人一样在构造函数中进行初始化即可:)