I have a datagrid with a column containing a ComboBox. I've set the Name for my combobox, but this name is not visible in code, why?
<DataGrid ...>
<DataGrid.Columns>
<DataGrid.TemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox Name="mex" Style="{DynamicResource ComboBoxStyle}"
ItemsSource="{Binding Path=combolist}"
SelectionChanged="status_SelectionChanged" Height="auto" Width="Auto">
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGrid.TemplateColumn>
...
</DataGrid.Columns>
</DataGrid>
In C# code mex is empty, not visible, why?
I tried x:Name="mex" as well, but it is still not visible.
c#:
mex.ItemsSource = dt;
undifined mex
A DataGridColumn is never actually in the Logical or Visual Tree; it is always a DataGridRow with DataGridCells, since they are automatically created for each row in the DataGrid.
The only way to reach your component is to build a complex Binding or find it using a Logical or Visual Tree helper.
BTW you should set your ItemsSource of your ComboBox through Bindings to available data from your row. You can't create bindings using ElementName within a DataGridTemplateColumn as again it is not in the Logical or Visual Tree.
I found an interesting link that explains the Visual Tree of a DataGrid: http://blogs.msdn.com/b/vinsibal/archive/2008/08/14/wpf-datagrid-dissecting-the-visual-layout.aspx.
You cannot directly reference elements when they are stored within an items template. Normally you'd want to allow the viewmodel to handle the bindings by setting the datacontext to the parent object and then allow the elements within the items template to pick this up. However based upon your question it looks as if you are attempting to do this directly from code behind.
Here are two similar questions and solutions for setting up the datacontext of an item as well as referencing an element within an items template. Hope this helps
Access parent DataContext from DataTemplate
and
WPF - ItemsControl - How do I get find my "CheckBox" item that is in the ItemTemplate?
because template is used by all rows.if name is usable .must have the same name in visual tree at one time.
Related
So, I have this ListView that needs to use some custom compare functions depending on what is bound.
Right now the only solution I have found so far is to have a custom property to declare (SortablePropertyName) what has been used as binding source, when using CellTemplates for binding more complex objects, such as object with both icon and text.
...
<ui:MyListView Grid.Row="1" ItemsSource="{Binding SubComponents}" SelectionChanged="SubComponentSelectionChanged" SelectionMode="Extended" VirtualizingStackPanel.IsVirtualizing ="False" Margin="2" DefaultSortingColumnHeader="Label" Grid.ColumnSpan="2">
<ui:MyListView.View>
<GridView>
<ui:MyGridViewColumn Header="Solution" Width="200" SortBy="Context" SortablePropertyName="SolutionVisualizationViewModel">
<GridViewColumn.CellTemplate>
<DataTemplate>
<bcp:MyObjectVisualizationView DataContext="{Binding SolutionVisualizationViewModel}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</ui:MyGridViewColumn>
...
Because later on when dealing with sorting I need information of what property of the ViewModel that has been used for current column.
foreach (MyGridViewColumn column in columns)
{
//Sort by context
if (column.SortBy == MyListViewSorting.SortOption.Context)
{
if (column.SortDirectionType == MyListViewSorting.SortDirectionType.Ascending)
{
listViewCollection.CustomSort = new ContextComparer(column.SortablePropertyName);
}
...
I can by adding DependencyObject data = column.CellTemplate.LoadContent() as DependencyObject; get hold of what view has been used, but still not what I want.
Is there away to find out this binding 'DataContext="{Binding VisualizationViewModel}' associated with a column without having to use a property?
Is there any "links" to be found between bindings and a GridViewColumn to hopefully solve this problem?
Is there away to find out this binding 'DataContext="{Binding VisualizationViewModel}' associated with a column without having to use a property?
You could realize the template using the LoadContent() method and check the DataContext property of the root element in it.
Or, assuming that the template has already been applied, you could use GetCellContent method to get a reference to the root element.
You may also override the GenerateElement method.
But using a property is probably easier.
A template is just a template and there is no element instantiated, binding applied och source value being resolved until it's actually applied. The column doesn't care/know what's in its CellTemplate. It just realizes the template.
<dxg:GridColumn.EditTemplate>
<ControlTemplate>
<dxe:ComboBoxEdit
HorizontalContentAlignment="Left"
ItemsSource="{Binding HizmetSaglayiciList}"
SelectedItem="{Binding Hiz_Sag_Id, Mode=TwoWay}"
ValueMember="Hiz_Sag_Id"
IsTextEditable="False"
AllowNullInput="False"
AutoComplete="False"
ImmediatePopup="False"
EditMode="InplaceActive"/>
</ControlTemplate>
</dxg:GridColumn.EditTemplate>
I have global list called HizmetSaglayiciList, but
The combobox does not open when I press the edit button.
I am writing missing any place.
I think this is one of those cases in which the DataContext is not accessible as certain elements (in this case dxg:GridColumn) are not part of visual or logical tree. A solution may be using a Freezable class. Check this Link.
DataContext for the ComboBoxEdit is not the same as for the GridControl, that's why ItemSource binding fails. Assuming your GridControl has a name (let's say it's x:Name="gridTest"), you can simply do the following:
ItemsSource="{Binding DataContext.HizmetSaglayiciList, ElementName=gridTest}"
Actually, you can bind ItemSource to any named element's DataContext.
I'm new to WPF and I have this ListBox which I want to instantiate with a specific ListBoxItem, so the user knows what to do with the ListBox.
<ListBox Name="DbListBox"
Grid.Column="3"
HorizontalAlignment="Left"
Height="246"
Margin="0,99,0,0"
Grid.Row="1"
VerticalAlignment="Top"
Width="211"
SelectionMode="Single"
SelectedItem="{Binding Path=selectedDB,Mode=TwoWay}"
AllowDrop="True"
Drop="DbListBox_Drop">
<ListBoxItem Name="ListBoxItem" FontStyle="Italic">Drag .db file here or add below</ListBoxItem>
</ListBox>
Then I have some code which adds a collection of items to the ItemsSource of this ListBox, but I can't do that since the ItemsSource is not empty
DbListBox.ItemsSource = DbCollection;
My question is, how can I start up the ListBox with the item inserted first, and then when DbCollection is added to it, it simply overwrites the first ListBoxItem?
When using WPF properly, we'd normally have something like this, where a collection property would be data bound to the ListBox.ItemsSource property:
<ListBox ItemsSource="{Binding SomeCollectionProperty}" />
Once we have this XAML, we don't need to touch the ListBox again, as we can add or remove items from the data bound collection and they will magically appear (or disappear) from the ListBox:
SomeCollectionProperty.Add(new SomeDataType());
SomeCollectionProperty.Remove(someItemFromCollection);
The SomeDataType used here is up to you... it depends on what you want to display in your items. If it was just a plain string for example, then you could simply do this to add your initial item into the collection:
SomeCollectionProperty.Add("Drag .db file here or add below");
If you wanted to make that item look different to the others then you'd need to data bind a custom class that has a Text property and FontStyle property for example. You could data bind these properties in a DataTemplate to design each item to be exactly as you want it. However, that's a completely different question.
To find out more about these things, you can read the Data Binding Overview and Data Templating Overview page on MSDN.
I have a ListView which contains a collection of objects as itemssource and the selected object as SelectedItem.
<ListView Margin="5 0 5 0" ItemsSource="{Binding ObjectCollection}" SelectedItem="{
Binding SelectedObject}" Grid.Row="1">
Inside the ListView.View I have several GridViewColumns which each have a CellTemplate
<GridViewColumn CellTemplate="{StaticResource ReferenceToCellTemplate}" Header="{
Binding ColumnName, Converter={StaticResource upperConverter}}" Width="90"
HeaderContainerStyle="{StaticResource StaticGridViewColumnHeaderStyleWhite}"/>
An example of such a template:
<DataTemplate x:Key="ReferenceToCellTemplate">
<ComboBox ItemsSource="{Binding PossibleValuesForProperty, UpdateSourceTrigger=
PropertyChanged}" SelectedItem="{Binding SelectedProperty, UpdateSourceTrigger=
PropertyChanged}" SelectionChanged="Protocol_ComboBox_SelectionChanged"/>
</DataTemplate>
Now for the issue:
Say that I have 2 comboboxes in this listview. for example a combobox with different software and another with the different versions of this software.
Whenever the software has changed in a certain row, the possible versions should be updated.
The question:
How do I know which object the software combobox belongs too so that I can adjust the possible versions for this object?
When you change the value inside the combobox, this doesn't mean that the row is selected. So when I try to adjust the versions along with the selected row, I might as well be adjust the wrong row.
So the way I see it there are 2 possibilities:
Select the given row whenever something inside that row is adjusted/selected
Get to know which row the changed/selected control is in without selecting it
Any help would be much appreciated.
The solution is to not use an event handler for when the property is changed but just to handle the change in the properties for the row object. So when the property for "software" changes, call a method which adjust the "PossibleVersions" property for this software. All of this inside the VM for the row object.
Basic beginner MVVM mistake I guess
I'm building a custom WPF control that derives from TabControl. In the ControlTemplate, I'm using a ItemsControl to display a list that is being bound from the template (an observable collection of type FileMenuItem). During program execution, I'm getting the following error in the output window:
ItemTemplate and ItemTemplateSelector
are ignored for items already of the
ItemsControl's container type;
Type='FileMenuItem'
The type FileMenuItem is derived from MenuItem. If I change the base class to DependencyObject, the code actually runs and the template is applied (so that's an option). I googled the error and couldn't find anything about it, has anyone run into this while developing custom controls? Even though I have a workaround, I'd like to understand what's happening, and I think using the MenuItem as a base class is a cleaner implementation.
I can post more code if it would help. Thanks!
The purpose of a DataTemplate (like ItemTemplate) is to provide a visualization for a data object. Specifically, it defines a set of elements to add to the visual tree in place of the data given to an ContentPresenter or ItemsPresenter. In your case your source list is a collection of objects that are already able to be added directly to the visual tree for display in the UI.
You can see this in the following simplified example where only "Three" shows up in Red because the first two items are defined in a form that can be displayed directly by ComboBox.
<ComboBox>
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" Foreground="Red"/>
</DataTemplate>
</ComboBox.ItemTemplate>
<ComboBoxItem>One</ComboBoxItem>
<ComboBoxItem>Two</ComboBoxItem>
<sys:String>Three</sys:String>
</ComboBox>