Change the content of a User Control from the mui Link (WPF) - c#

I encounter some issues with my project. I have a moderntab that I fill of link by a request into a database. The result of my request return a list of string that will be the displayname of the link of my moderntab. I create all the link in behind code, and I want that when I click into a link, the content of the usercontrol change in function of the displayname.
Currently, I know how to take the displayname when the it detect that I change source. But I want to have the same Source for all the link, and the content of the usercontrol change in function of the displayname of the selected link.
That's my xaml code of the moderntab :
<Grid Style="{StaticResource ContentRoot}">
<mui:ModernTab Layout="List" Name="listEcole" SelectedSourceChanged="listEcole_SelectedSourceChanged"/>
</Grid>
That's is the code behind :
public ListEcoles()
{
InitializeComponent();
List<string> listEcoles = MainWindow._RE.ListEcoles();
foreach (string nomEcole in listEcoles)
listEcole.Links.Add(new Link() { DisplayName = nomEcole, Source = new Uri("/Controles/EcoleControl.xaml", UriKind.Relative) });
}
private void listEcole_SelectedSourceChanged(object sender, SourceEventArgs e)
{
var selectedLink = listEcole.Links.FirstOrDefault(x => x.Source == listEcole.SelectedSource);
if (selectedLink != null)
{
string selectedDisplayName = selectedLink.DisplayName;
MessageBox.Show(selectedDisplayName);
}
}
It doesn't work here because every sources of my link are the same, so the event never proceed.
Can some one help me please.

Handle another event like the PreviewMouseLeftButtonUp then. You could use a helper method that finds the ListBoxItem in the visual tree and then get a reference to the corresponding Link object using the ListBoxItem's DataContext property.
Try this:
public ListEcoles()
{
InitializeComponent();
List<string> listEcoles = MainWindow._RE.ListEcoles();
foreach (string nomEcole in listEcoles)
listEcole.Links.Add(new Link() { DisplayName = nomEcole, Source = new Uri("/Controles/EcoleControl.xaml", UriKind.Relative) });
listEcole.PreviewMouseLeftButtonUp += ListEcole_MouseLeftButtonUp;
}
private void ListEcole_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
ListBoxItem lbi = e.OriginalSource as ListBoxItem;
if (lbi == null)
{
lbi = FindParent<ListBoxItem>(e.OriginalSource as DependencyObject);
}
if (lbi != null)
{
Link selectedLink = lbi.DataContext as Link;
if (selectedLink != null)
{
string selectedDisplayName = selectedLink.DisplayName;
MessageBox.Show(selectedDisplayName);
}
}
}
private static T FindParent<T>(DependencyObject dependencyObject) where T : DependencyObject
{
var parent = VisualTreeHelper.GetParent(dependencyObject);
if (parent == null) return null;
var parentT = parent as T;
return parentT ?? FindParent<T>(parent);
}

Related

WPF - How to get treeviewitem when user clicks on the checkbox

I have defined the ItemTemplate for the TreeView in the code behind C#. In that ItemTemplate, I have a CheckBox and a label defined in it. The Tag and Text properties of the CheckBox and label is binded with the data.
Now, I'd like to get the TreeViewItem object whenever the user clicks on the CheckBox. I used the click event on the CheckBox but that event didn't give me the TreeViewItem's object.
I would really appreciate if someone could explain the solution for it.
Here's the code written in C#:
public static void FillTree()
{
//assign treeview itemtemplate
BIMExplorerUserControl.Instance.BimTreeView.ItemTemplate = GetHeaderTemplate();
BIMExplorerUserControl.Instance.BimTreeView.ItemContainerGenerator.StatusChanged += new EventHandler(ItemContainerGenerator_StatusChanged);
foreach (var category in ViewModel.Instance.DefaultExplorerView)
{
BIMExplorerUserControl.Instance.BimTreeView.Items.Add(category);
}
}
public static DataTemplate GetHeaderTemplate()
{
//create the data template
DataTemplate dataTemplate = new DataTemplate();
//create stack pane;
FrameworkElementFactory stackPanel = new FrameworkElementFactory(typeof(StackPanel));
stackPanel.Name = "parentStackpanel";
stackPanel.SetValue(StackPanel.OrientationProperty, Orientation.Horizontal);
// Create check box
FrameworkElementFactory checkBox = new FrameworkElementFactory(typeof(CheckBox));
checkBox.Name = "chk";
checkBox.SetValue(CheckBox.NameProperty, "chk");
checkBox.SetValue(CheckBox.TagProperty, new Binding());
checkBox.SetValue(CheckBox.MarginProperty, new Thickness(2));
checkBox.SetValue(CheckBox.TagProperty, new Binding() { Path = new PropertyPath("Name") });
checkBox.AddHandler(CheckBox.ClickEvent, new RoutedEventHandler(CheckedEvent));
stackPanel.AppendChild(checkBox);
// create text
FrameworkElementFactory label = new FrameworkElementFactory(typeof(TextBlock));
label.SetBinding(TextBlock.TextProperty, new Binding() { Path = new PropertyPath("Name") });
label.SetValue(TextBlock.ToolTipProperty, new Binding());
stackPanel.AppendChild(label);
//set the visual tree of the data template
dataTemplate.VisualTree = stackPanel;
return dataTemplate;
}
static void ItemContainerGenerator_StatusChanged(object sender, EventArgs e)
{
if (BIMExplorerUserControl.Instance.BimTreeView.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)
{
foreach (var category in ViewModel.Instance.DefaultExplorerView)
{
TreeViewItem item = (TreeViewItem)BIMExplorerUserControl.Instance.BimTreeView.ItemContainerGenerator.ContainerFromItem(category);
if (item == null) continue;
item.IsExpanded = false;
if (item.Items.Count == 0)
{
foreach (var element in category.Elements)
{
item.Items.Add(element);
}
}
}
}
}
private static void CheckedEvent(object sender, RoutedEventArgs e)
{
CheckBox checkbox = (CheckBox)e.Source;
var name = checkbox.Tag.ToString();
}
You could use the following helper method to get a reference to the CheckBox's parent TreeViewItem in the visual tree:
private static T FindParent<T>(DependencyObject dependencyObject) where T : DependencyObject
{
var parent = VisualTreeHelper.GetParent(dependencyObject);
if (parent == null) return null;
var parentT = parent as T;
return parentT ?? FindParent<T>(parent);
}
Usage:
private static void CheckedEvent(object sender, RoutedEventArgs e)
{
CheckBox checkbox = (CheckBox)sender;
var name = checkbox.Tag.ToString();
TreeViewItem tvi = FindParent<TreeViewItem>(checkbox);
//...
}

Getting selected rows of report files from a WPF Datagrid on button click

This is my first question on stackoverflow and I am entirely new to programming in C# so please bear with me. I created an application using WPF in which I displayed a list of files with .rpt extension in a datagrid. The datagrid contains the list of filenames and there is also a checkbox column in the datagrid. These files are populated in the grid dynamically from a folder browser when I click on a button. I am stuck on the part of retreiving these files for printing when I click on a second button (print, as I need to call a service to print the selected files).
This is the code snippet that I have tried until now:
public partial class MainWindow : Window
{
public class ReportFile
{
public string Path { get; set; }
public string FileName { get; set; }
}
private void Button_Click(object sender, RoutedEventArgs e)
{
string inputPath = AppDomain.CurrentDomain.BaseDirectory;
System.Windows.Forms.FolderBrowserDialog fldDlg = new System.Windows.Forms.FolderBrowserDialog();
fldDlg.SelectedPath = AppDomain.CurrentDomain.BaseDirectory;
DialogResult result = fldDlg.ShowDialog();
foreach (string str in Directory.GetFiles(fldDlg.SelectedPath))
{
ReportFile reportFile = new ReportFile();
reportFile.Path = str;
reportFile.FileName = System.IO.Path.GetFileName(str);
dataGrid1.Items.Add(reportFile);
}
}
private void button_Click_1(object sender, RoutedEventArgs e)
{
foreach (ReportFile drv in dataGrid1.SelectedItems.OfType<ReportFile>())
{
if (drv != null)
{
DataRow row = drv.Row;
Title = row.ItemArray[3].ToString();
System.Windows.MessageBox.Show(Title.ToString());
}
}
var TransactionFactory = new TransactionFactory();
var Transaction = TransactionFactory.NewTransactionString();
var EnvironmentValue = (string)cmbEnvironment.SelectedValue;
var CirieEngineServiceClientFactory = new CirieEngineServiceClientFactory(EnvironmentValue);
var CirieEngineServiceClient = CirieEngineServiceClientFactory.NewCirieEngineServiceClient();
var Form = new Cirie.Form()
{
Path = string.Empty,
Title = string.Empty
};
var PackageID = Convert.ToInt16(txtPackageID.SelectedText);
var Generation = Convert.ToInt16(txtGeneration.SelectedText);
var formList = new List<Cirie.Form>();
var stream = CirieEngineServiceClient.PrintFormCollection
(Transaction,
new Collection<Cirie.Form>(formList),
PackageID,
Generation
);
}
}
But I am not sure if it is correct since there is an exception being thrown: Unable to cast object of type 'ReportFile' to type 'System.Data.DataRowView'
I would really appreciate help on this one please!
You could use the OfType method to cast the SelectedItems to ReportFile objects and then access any properties of the ReportFile class:
foreach (ReportFile drv in dataGrid1.SelectedItems.OfType<ReportFile>())
{
//...
}

Find PlaceHolder another PlaceHolder

I've strange problem... :/
I have on my page PlaceHolder, where I generate dynamically more PlaceHolders.
I've stored names of this dynamicaly created PlaceHolders.
When I try to find any of this PlaceHolders - I've got error null reference to an Object.
Please help! :)
private void btnMoreInfo_Click(object sender, EventArgs e)
{
Button button = sender as Button;
string[] componentName = button.ID.Split('_');
String controlName = null;
foreach (String singlePlaceHolder in placeHolderNames)
{
if (singlePlaceHolder.Contains(componentName[0]))
controlName = singlePlaceHolder;
}
Control cph = this.Master.FindControl(controlName);
Label helperlabel = new Label();
helperlabel.Text = "That one!";
cph.Controls.Add(helperlabel);
cph.Visible = true;
}
I changed code to this, and it's working now:
var cph = FindControlRecursive(this.Master, controlName);
plus I added new method:
private Control FindControlRecursive(Control root, string id)
{
if(root.Id==id)
{
return root;
}
foreach (Control c in root.Controls)
{
Control t= FindControlRecursaive(c, id);
if (t !=null)
{
return t;
}
}
return null;
}

Unable to drag file to Windows Explorer from a WPF ListView

I am trying to drag a ListView item and drop it as a copy of file from the location stored in that ListView item. I am successfully getting the location from the ListView item when I start dragging but unable to signal Operating System to copy that file to the specified location.
private Point start;
ListView dragSource = null;
private void files_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
this.start = e.GetPosition(null);
ListView parent = (ListView)sender;
dragSource = parent;
object data = GetDataFromListBox(dragSource, e.GetPosition(parent));
Hide();
if (data != null)
{
string dataStr = ((UserData)data).Data.ToString();
string filepath = new System.IO.FileInfo(dataStr).FullName;
DataObject fileDrop = new DataObject(DataFormats.FileDrop, filepath);
DragDrop.DoDragDrop((ListView)sender, fileDrop, DragDropEffects.Copy);
}
}
private static object GetDataFromListBox(ListView source, Point point)
{
UIElement element = source.InputHitTest(point) as UIElement;
if (element != null)
{
object data = DependencyProperty.UnsetValue;
while (data == DependencyProperty.UnsetValue)
{
data = source.ItemContainerGenerator.ItemFromContainer(element);
if (data == DependencyProperty.UnsetValue)
{
element = VisualTreeHelper.GetParent(element) as UIElement;
}
if (element == source)
{
return null;
}
}
if (data != DependencyProperty.UnsetValue)
{
return data;
}
}
return null;
}
The second method GetDataFromListBox() I found on one of the SO questions' answer. This method extracts the correct data from the ListBox or ListView.
I am new to WPF. Please tell me what I am missing?
Finally, I found a solution here: http://joyfulwpf.blogspot.in/2012/06/drag-and-drop-files-from-wpf-to-desktop.html
The solution was to assign file drop list using SetFileDropList() method, instead of inside DataObject's constructor. Following is my modified working code:
ListView parent = (ListView)sender;
object data = parent.SelectedItems;
System.Collections.IList items = (System.Collections.IList)data;
var collection = items.Cast<UserData>();
if (data != null)
{
List<string> filePaths = new List<string>();
foreach (UserData ud in collection)
{
filePaths.Add(new System.IO.FileInfo(ud.Data.ToString()).FullName);
}
DataObject obj = new DataObject();
System.Collections.Specialized.StringCollection sc = new System.Collections.Specialized.StringCollection();
sc.AddRange(filePaths.ToArray());
obj.SetFileDropList(sc);
DragDrop.DoDragDrop(parent, obj, DragDropEffects.Copy);
}

Add menu item to .cs files (only) in Visual Studio solution explorer?

I want to add a context menu item to .cs files in solution explorer in VS 2010? I could add it to the project, but not only to .cs files? Any help would be appreciated.
In your OnBeforeQueryStatus Method you need to get the currently selected object and determine the file type, then you can set the Visible property for the MenuCommand.
To enabled OnBeforeQueryStatus you will need to add the following Attribute to your package:
[ProvideAutoLoad(Microsoft.VisualStudio.Shell.Interop.UIContextGuids.SolutionExists)]
public sealed class YourPackage : Package
Then in your Command Constructor you will need to bind your callback to BeforeQueryStatus:
...
var commandService = this.ServiceProvider.GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
if (commandService == null) return;
var menuCommandId = new CommandID(CommandSet, CommandId);
var menuItem = new OleMenuCommand(this.MenuItemCallback, menuCommandId);
menuItem.BeforeQueryStatus +=
new EventHandler(OnBeforeQueryStatus);
commandService.AddCommand(menuItem);
...
OnBeforeQueryStatus:
private void OnBeforeQueryStatus(object sender, EventArgs e)
{
var myCommand = sender as OleMenuCommand;
if (null == myCommand) return;
var selectedObject = Util.GetProjectItem();
myCommand.Visible = selectedObject.Name.EndsWith(".cs") && this.Enabled;
}
GetProjectItem:
public static ProjectItem GetProjectItem()
{
IntPtr hierarchyPointer, selectionContainerPointer;
Object selectedObject = null;
IVsMultiItemSelect multiItemSelect;
uint projectItemId;
var monitorSelection =
(IVsMonitorSelection)Package.GetGlobalService(
typeof(SVsShellMonitorSelection));
monitorSelection.GetCurrentSelection(out hierarchyPointer,
out projectItemId,
out multiItemSelect,
out selectionContainerPointer);
var selectedHierarchy = Marshal.GetTypedObjectForIUnknown(
hierarchyPointer,
typeof(IVsHierarchy)) as IVsHierarchy;
if (selectedHierarchy != null)
{
ErrorHandler.ThrowOnFailure(selectedHierarchy.GetProperty(
projectItemId,
(int)__VSHPROPID.VSHPROPID_ExtObject,
out selectedObject));
}
return selectedObject as ProjectItem;
}
And with all of that you should be only seeing your button on project files that end with .cs

Categories