I have a DataGrid. The ItemsSource of this DataGrid is set in the Completed event of a WCF call.However, when adding a Detail Datagrid inside the master grids DataTemplate and naming it appropriately... Ineed to fill it master grids selection change event but my codebehind does not recognise the detail grid. I cant set the ItemsSource of grdDetail like I do with grdMaster.So how i can fill my detail datagrid ?
Xaml File
<Grid x:Name="LayoutRoot">
<sdk:DataGrid x:Name="dgCustList" AutoGenerateColumns="False" Background="Transparent" SelectionChanged="dgCustList_SelectionChanged">
<sdk:DataGrid.RowDetailsTemplate>
<DataTemplate>
<StackPanel x:Name="stkPanel">
<sdk:DataGrid x:Name="dgCustDetail" RowDetailsVisibilityMode="VisibleWhenSelected" AutoGenerateColumns="False" Background="Transparent"/>
</StackPanel>
</DataTemplate>
</sdk:DataGrid.RowDetailsTemplate>
</sdk:DataGrid>
<Grid.Projection>
<PlaneProjection x:Name="Projection"/>
</Grid.Projection>
</Grid>
And CodeBehind
public MusteriListe()
{
InitializeComponent();
var stb1 = new Storyboard { Duration = new Duration(TimeSpan.FromSeconds(1)), SpeedRatio = 3 };
var daY1 = new DoubleAnimation { From = 0.00, To = 90.00 };
Storyboard.SetTargetName(daY1, "Projection");
Storyboard.SetTargetProperty(daY1, new PropertyPath("RotationX"));
stb1.Children.Add(daY1);
this.Resources.Add("EndOfPage", stb1);
var stb = new Storyboard();
stb.Duration = new Duration(TimeSpan.FromSeconds(1));
stb.SpeedRatio = 3;
var daY = new DoubleAnimation { From = -90.00, To = 0.00 };
Storyboard.SetTargetName(daY, "Projection");
Storyboard.SetTargetProperty(daY, new PropertyPath("RotationX"));
stb.Children.Add(daY);
Resources.Add("StartOfPage", stb);
dgCustList.Columns.Add(new DataGridTextColumn
{
Header = "ID",
Binding = new Binding("CustomerID")
});
dgCustList.Columns.Add(new DataGridTextColumn
{
Header = "Müşteri Ad",
Binding = new Binding("CustomerName")
});
dgCustList.Columns.Add(new DataGridTextColumn
{
Header = "Müşteri Soyad",
Binding = new Binding("CustomerSurname")
});
dgCustList.Columns.Add(new DataGridTextColumn
{
Header = "Müşteri Tel",
Binding = new Binding("CustomerPhone")
});
LoadGrid();
}
private void LoadGrid()
{
var client = new EczServiceClient();
client.CustomerInfoCompleted += client_CustomerInfoCompleted;
client.CustomerInfoAsync();
}
void client_CustomerInfoCompleted(object sender, CustomerInfoCompletedEventArgs e)
{
dgCustList.ItemsSource = e.Result;
}
private void dgCustList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var customer = dgCustList.SelectedItem as CustomerInfo;
if (customer == null) return;
var client = new EczServiceClient();
client.CustomerDetailCompleted += client_CustomerDetailCompleted;
client.CustomerDetailAsync(customer.CustomerID);
}
void client_CustomerDetailCompleted(object sender, CustomerDetailCompletedEventArgs e)
{
IN HERE I WANT TO FILL DATAGRID LIKE MASTER GRID BUT ITS NOT LET ME ( dgCustDetail.ItemSource = e.Result)
}
You did NOTdefine binding for you detail data grid and you set the autogenerate columns to false. You need to define the binding either in XAML or in code behind before the client_CustomerDetailCompleted event fires. Simply setting the item source alone won't work because the detail datagrid does not contain columns. This is where MVVM pattern comes in handy.
Related
I'm working on a C# application, where I'm trying to create my own filtering mechanism for filtering a Telerik RadGridView control.
My RadGridView control looks as follows (in the xaml file, I've left some open lines for showing the part where I define my filter):
<telerik:RadGridView x:Name="PartsGridView"
AutoGenerateColumns="False"
CanUserFreezeColumns="False"
FilteringMode="Popup"
FilterOperatorsLoading="Grid_FilterOperatorsLoading"
ItemsSource="{Binding PagedSource, ElementName=PartsRadDataPager}"
IsSynchronizedWithCurrentItem="False"
SelectedItem="{Binding SelectedPart}"
SelectionMode="Single"
ShowInsertRow="False"
EnableRowVirtualization="True"
RowLoaded="PartsGridView_RowLoaded"
FieldFilterEditorCreated="FieldFilterEditorCreated"
IsFilteringAllowed="True"
DistinctValuesLoading="PartsGridView_DistinctValuesLoading"
Grouped="PartsGridView_Grouped">
<telerik:RadGridView.GroupDescriptors>
<telerik:GroupDescriptor Member="Name" DisplayContent="Article"/>
</telerik:RadGridView.GroupDescriptors>
<telerik:RadGridView.FilterDescriptors/>
<telerik:RadGridView.Columns>
...
<telerik:GridViewDataColumn DataMemberBinding="{Binding Article.CustomerReference}"
Header="Client"
IsReadOnly="True"
Name="Client">
<telerik:GridViewDataColumn.FilteringControl>
<local:Myfilter Column="{Binding ElementName=Client}"/>
</telerik:GridViewDataColumn.FilteringControl>
</telerik:GridViewDataColumn>
</telerik:RadGridView.Columns>
</telerik:RadGridView>
The corresponding source code is as follows (I've only shown the OnFilter, it's the idea to extend the filtering possibilities to regular expressions, but let's start making the regular filter work first):
public partial class MyFilter : System.Windows.Controls.UserControl,
IFilteringControl
{
private GridViewDataColumn column;
private CompositeFilterDescriptor compositeFilter;
private Telerik.Windows.Data.FilterDescriptor textFilter;
private void OnFilter(object sender, RoutedEventArgs e)
{
//var reg = new Regex(textBox.Text.Replace("*", ".*"));
// var descriptor = new FilterDescriptor<string>
// { FilteringExpression = o => reg.IsMatch(o) };
compositeFilter = new CompositeFilterDescriptor();
textFilter = new Telerik.Windows.Data.FilterDescriptor(Column.Name
, Telerik.Windows.Data.FilterOperator.IsEqualTo
, null);
compositeFilter.FilterDescriptors.Add(textFilter);
textFilter.Value = TextBox;
if (!Column.DataControl.FilterDescriptors.Contains(compositeFilter))
{
Column.DataControl.FilterDescriptors.Add(compositeFilter);
}
IsActive = true;
}
When debugging, I go into the OnFilter() function but instead of just filtering, I don't see any data in the RadGridView anymore.
Does anybody have an idea what I'm doing wrong?
Edit: In case the question is not clear, don't hesitate asking for more information.
Try this:
private void OnFilter(object sender, RoutedEventArgs e)
{
//var reg = new Regex(textBox.Text.Replace("*", ".*"));
// var descriptor = new FilterDescriptor<string>
// { FilteringExpression = o => reg.IsMatch(o) };
//compositeFilter = new CompositeFilterDescriptor();
textFilter = new Telerik.Windows.Data.FilterDescriptor(Column.Name
, Telerik.Windows.Data.FilterOperator.IsEqualTo
, null);
//compositeFilter.FilterDescriptors.Add(textFilter);
textFilter.Value = TextBox;
if (!Column.DataControl.FilterDescriptors.Contains(textFilter))
{
Column.DataControl.FilterDescriptors.Add(textFilter);
}
IsActive = true;
}
u can also try this:
private void OnFilter(object sender, RoutedEventArgs e)
{
compositeFilter = new CompositeFilterDescriptor();
textFilter = new Telerik.Windows.Data.FilterDescriptor(Column.Name, Telerik.Windows.Data.FilterOperator.IsEqualTo, null);
compositeFilter.FilterDescriptors.Add(textFilter);
textFilter.Value = TextBox;
if (!Column.DataControl.FilterDescriptors.Contains(compositeFilter))
{
Column.DataControl.FilterDescriptors.Add(compositeFilter);
}
IsActive = true;
}
I use SearchBar to search from listView and I have other controls
but when page load just SearchBar appear and other controls disappear
like this image
and when search then select from listView the disappeared controls appears
like this image
my xaml code :
<StackLayout>
<SearchBar x:Name="search_trade"
TextChanged="search_trade_TextChanged"
/>
<ListView x:Name="list" ItemSelected="list_ItemSelected" >
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding Name}" ></TextCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Editor x:Name="edit_trade"
FontSize="14"/>
</StackLayout>
my c# code :
private void search_trade_TextChanged(object sender, TextChangedEventArgs e)
{
if (search_trade.Text.Trim()==string.Empty)
{
list.IsVisible = false;
}
list.IsVisible = true;
if (string.IsNullOrEmpty(e.NewTextValue))
{
list.ItemsSource = tempdata;
}
else
{
list.ItemsSource = tempdata.Where(x => x.Name.ToLower().StartsWith(e.NewTextValue));
}
}
private void list_ItemSelected(object sender, SelectedItemChangedEventArgs e)
{
var item = (Contacts)e.SelectedItem;
edit_trade.Text = item.Name.ToString();
search_trade.Text = "";
list.IsVisible = false;
edit_trade.IsReadOnly = true;
}
code c# that I initially set the ItemsSource :
public Anti_biotic()
{
InitializeComponent();
active();
years_months();
frame_view.IsVisible = false;
trade();
}
private void trade()
{
tempdata = new List<Contacts>
{
new Contacts() { Name = "Amoclawin228.5mg/5mlsusp60ml"},
new Contacts() { Name = "Amoclawin 457mg / 5ml susp 60 ml"},
new Contacts() { Name = "Amoflux 250 mg susp 100 ml"},
};
}
how can I solve this issue?
you are not assigning the ListView's ItemsSource when the page loads. If the ListView doesn't have any data then it won't display anything
public Anti_biotic()
{
InitializeComponent();
active();
years_months();
frame_view.IsVisible = false;
// this method creates tempdata but doesn't do anything with it
trade();
// add this
list.ItemsSource = tempdata;
}
This is my code, There is one listbox in right side, the listbox item is added to the another list box item inside the grid. The Grid is added dynamically by using the context menu. Till it is working fine. But now I want to move the whole list not list items, to the grid dynamically at runtime. Please anyone guide me to drag the whole list and placing the whole list to grid at runtime dynamically.
<Grid>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<WrapPanel
x:Name="mainPanel"
Grid.Column="0"
Background="#F0F0F0"
ScrollViewer.VerticalScrollBarVisibility="Auto">
<WrapPanel.ContextMenu>
<ContextMenu>
<MenuItem Click="MenuItem_Click" Header="Add Pabel" />
</ContextMenu>
</WrapPanel.ContextMenu>
</WrapPanel>
<ListBox
Name="memberCollection"
Grid.Column="1"
Width="150"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
PreviewMouseLeftButtonDown="memberCollection_PreviewMouseLeftButtonDown">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<Label Name="Name" Content="{Binding Name}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Grid>
Code Behind
ObservableCollection<Member> member = new ObservableCollection<Member>();
public MainWindow()
{
InitializeComponent();
member.Add(new Member { Name = "Karthick", ID = "20011", Address = "10, MainRoad, Chennai" });
member.Add(new Member { Name = "Suresh", ID = "20012", Address = "11, MainRoad, Madurai" });
member.Add(new Member { Name = "Arun", ID = "20013", Address = "12, MainRoad, Selam" });
member.Add(new Member { Name = "Gokul", ID = "20014", Address = "13, MainRoad, Coimbature" });
member.Add(new Member { Name = "Vishnu", ID = "20015", Address = "14, MainRoad, Goa" });
memberCollection.ItemsSource = member;
}
private void MenuItem_Click(object sender, RoutedEventArgs e)
{
Grid panel = new Grid();
panel.MinHeight = 150;
panel.MinWidth = 150;
panel.Height = 150;
panel.Width = 150;
panel.Margin = new Thickness(15,15,0,10);
Grid gridDrop = new Grid()
{
Background = Brushes.White,
HorizontalAlignment = HorizontalAlignment.Stretch,
VerticalAlignment = VerticalAlignment.Stretch
};
gridDrop.Drop += grid_Drop;
var panelTemplate = new DataTemplate();
var stackPanel = new FrameworkElementFactory(typeof(StackPanel));
stackPanel.SetValue(StackPanel.OrientationProperty, Orientation.Vertical);
var name = new FrameworkElementFactory(typeof(Label));
name.SetBinding(Label.ContentProperty, new Binding("Name"));
var id = new FrameworkElementFactory(typeof(Label));
id.SetBinding(Label.ContentProperty, new Binding("ID"));
var address = new FrameworkElementFactory(typeof(Label));
address.SetBinding(Label.ContentProperty, new Binding("Address"));
stackPanel.AppendChild(name);
stackPanel.AppendChild(id);
stackPanel.AppendChild(address);
panelTemplate.VisualTree = stackPanel;
ListBox listBox = new ListBox()
{
AllowDrop = true,
ItemTemplate = panelTemplate
};
gridDrop.Children.Add(listBox);
panel.Children.Add(gridDrop);
mainPanel.Children.Add(panel);
DataContext = new Member();
}
private void memberCollection_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
object selectedMember = memberCollection.SelectedItem as Member;
if (selectedMember != null)
{
DragDrop.DoDragDrop(memberCollection, selectedMember, DragDropEffects.Move);
}
}
private void grid_Drop(object sender, RoutedEventArgs e)
{
ListBox listContent = e.Source as ListBox;
if (listContent != null)
Console.WriteLine("", Grid.GetColumn(listContent), Grid.GetRow(listContent));
DataObject item = (((DragEventArgs)e).Data) as DataObject;
object Target = ((Grid)(sender)).DataContext;
if (Target != null)
{
object listItem = item.GetData(Target.GetType());
listContent.Items.Add(listItem);
}
}
If you only want to move the whole list and create a tile for each Member, then this is one way to go:
First of all, you should simplify your template and put it in the XAML.
XAML is much more efficient at handling any kind of template than the code behind
For your left mainPanel:
<ItemsControl x:Name="mainPanel" Grid.Column="0" ItemsSource="{Binding}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Background="#F0F0F0" AllowDrop="True" Drop="mainPanel_Drop">
<WrapPanel.ContextMenu>
<ContextMenu>
<MenuItem Click="MenuItem_Click" Header="Add Panel" />
</ContextMenu>
</WrapPanel.ContextMenu>
</WrapPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical" Background="White" AllowDrop="True" Margin="15,15,0,10" Width="150" MinWidth="150" Height="150" MinHeight="150">
<Label Content="{Binding Name}"/>
<Label Content="{Binding ID}"/>
<Label Content="{Binding Address}"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
And for your list (no much changes)
<ListBox
Name="memberCollection"
Grid.Column="1"
Width="150"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
ItemsSource="{Binding}"
PreviewMouseLeftButtonDown="memberCollection_PreviewMouseLeftButtonDown">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<Label Name="memberName" Content="{Binding Name}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I added two ObservableCollection to manage the Data
ObservableCollection<Member> member = new ObservableCollection<Member>();
ObservableCollection<Member> mainPanelMembers = new ObservableCollection<Member>();
public MainWindow()
{
InitializeComponent();
member.Add(new Member { Name = "Karthick", ID = "20011", Address = "10, MainRoad, Chennai" });
member.Add(new Member { Name = "Suresh", ID = "20012", Address = "11, MainRoad, Madurai" });
member.Add(new Member { Name = "Arun", ID = "20013", Address = "12, MainRoad, Selam" });
member.Add(new Member { Name = "Gokul", ID = "20014", Address = "13, MainRoad, Coimbature" });
member.Add(new Member { Name = "Vishnu", ID = "20015", Address = "14, MainRoad, Goa" });
memberCollection.DataContext = member;
mainPanel.DataContext = mainPanelMembers;
}
Then, the creation of a new Tile is much much more simplier:
private void MenuItem_Click(object sender, RoutedEventArgs e)
{
mainPanelMembers.Add(new Member());
}
If you want to copy the whole list, then you have to give the whole ObservableCollection to the DragDrop manager:
private void memberCollection_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
object collectionDataContext = memberCollection.DataContext;
if (collectionDataContext != null)
{
DataObject dragData = new DataObject("DataContext", collectionDataContext);
DragDrop.DoDragDrop(memberCollection, dragData, DragDropEffects.Move);
}
}
And when you drop it, you can simply add the Member one by one. You could also clear the collection before (but I didn't):
private void mainPanel_Drop(object sender, DragEventArgs e)
{
DataObject item = e.Data as DataObject;
object listItem = item.GetData("DataContext") as IEnumerable<Member>;
if (listItem != null)
{
foreach (Member member in (IEnumerable<Member>)listItem)
{
((ObservableCollection<Member>)mainPanel.DataContext).Add(member);
}
}
}
I'm not sure I understood very well what you wanted... I still don't know how you're using the Tile creation.
Let me know if you need to do something different.
The DataGrid columns are dynamically created in code behind. In order to bind the columns dynamically I have a Dictionary<string, obj> property, with the key as the column header, and the values.
and the columns gets bound to the dictionary like this:
var item = new DataGridTextColumn();
item.Width = new DataGridLength(1, DataGridLengthUnitType.Auto);
item.Header = name;
item.Binding = new Binding($"di[{name}].obj") { Mode = BindingMode.TwoWay };
It works fine, but I couldn't figure out how to get the values from the new row form DataGrid
I've created a test project and ExpandoObject worked for me. I was able to display dynamic column "FirstName" and also add new rows by editing grid rows
XAML:
<Grid Margin="0,0,0,56" Loaded="Grid_Loaded_1">
<DataGrid Name="MyGrid" ItemsSource="{Binding Items}" HorizontalAlignment="Left" Margin="69,33,0,0" VerticalAlignment="Top" Height="220" Width="389"/>
<Button Content="Button" HorizontalAlignment="Left" Height="22" Margin="339,286,0,-45" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
</Grid>
CS:
public partial class MainWindow : Window
{
public ViewModel Vm { get; set; }
public MainWindow()
{
InitializeComponent();
}
private void Grid_Loaded_1(object sender, RoutedEventArgs e)
{
Vm = new ViewModel();
Vm.Items = new ObservableCollection<ExpandoObject>();
DataContext = Vm;
var fieldName = "FirstName";
var item = new ExpandoObject() as IDictionary<string, Object>;
item.Add(fieldName, "Adam"); // Dynamically adding new fields
var eoItem = item as ExpandoObject;
Vm.Items.Add(eoItem);
// Dynamically adding new columns
var col = new DataGridTextColumn();
col.Width = new DataGridLength(1, DataGridLengthUnitType.Auto);
col.Header = fieldName;
col.Binding = new Binding(fieldName) { Mode = BindingMode.TwoWay };
MyGrid.Columns.Add(col);
}
private void Button_Click(object sender, RoutedEventArgs e)
{
}
}
public class ViewModel
{
public ObservableCollection<ExpandoObject> Items { get; set; }
}
I had similar problem some time ago. Below You can find my solution. Basically I needed to change AddingNewRow event. You will need to change types etc. to meet your needs but this should be rather easy.
private void AddingNewRow(object sender, AddingNewItemEventArgs e)
{
DictionaryRowData newRow = new DictionaryRowData();
for (int i = 0; i < dictionaryData.Columns.Count; i++)
{
newRow.Cells.Add(new DictionaryCellData());
}
e.NewItem = newRow;
}
Sorry, for not matching exactly your case, but I don't have time right now. I hope it will help
How do I convert the following ListView with ItemTemplate and Binding in the xaml file to equivalent C# code:
<ListView VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand"
ItemsSource="{Binding A}" ItemSelected="OnClick">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding b}" Detail="{Binding c}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Try something like this:
ListView lv = new ListView();
lv.HorizontalOptions = LayoutOptions.FillAndExpand;
lv.VerticalOptions = LayoutOptions.FillAndExpand;
lv.SetBinding(ListView.ItemsSourceProperty, new Binding("A"));
lv.ItemSelected += (sender, args) =>
{
onclick(sender, args);
}; //Remember to remove this event handler on dispoing of the page;
DataTemplate dt = new DataTemplate(typeof(TextCell));
dt.SetBinding(TextCell.TextProperty, new Binding("b"));
dt.SetBinding(TextCell.DetailProperty, new Binding("c"));
lv.ItemTemplate = dt;
For more complex Datatemplates do:
DataTemplate dt = new DataTemplate(() =>
{
var button = new Button();
button.SetBinding(Button.TextProperty, new Binding("Name"));
return new ViewCell { View = button };
});