Editable combobox overwrites my context menu - Fails - c#

I have been trying to use the code in the reply to Question
"Editable combobox overwrites my context menu" asked on asked Aug 30 '12 at 14:24
But it always errors with a nullreferenceerror on
(VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(combobox, 0), 2) as TextBox).ContextMenu = combobox.ContextMenu;
In order to minimize any environment problems I have added the code as a new project
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ComboBox IsEditable="True" ContextMenuService.ShowOnDisabled="True"
Name="combobox" Loaded="combobox_Loaded">
<ComboBox.ContextMenu>
<ContextMenu>
<MenuItem Header="test"></MenuItem>
</ContextMenu>
</ComboBox.ContextMenu>
<ComboBoxItem Content="Item1"></ComboBoxItem>
<ComboBoxItem Content="Item2"></ComboBoxItem>
</ComboBox>
</Grid>
</Window>
code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void combobox_Loaded(object sender, RoutedEventArgs e)
{
(VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(combobox, 0), 2) as TextBox).ContextMenu = combobox.ContextMenu;
}
}
}

This is working:
private void combobox_Loaded(object sender, RoutedEventArgs e)
{
(VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(combobox, 0), 2), 0) as TextBox).ContextMenu = combobox.ContextMenu;
}
You have to go another level.
Because the TextBox is inside a border.
You can use Snoop application to inspect the xaml tree.

Related

UserControl Data Binding retrieve value

with this simple code:
MainWindows:
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace itemcontrole_lesson
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public class TodoItem
{
public string Username { get; set; }
public int Completion { get; set; }
}
public partial class MainWindow : Window
{
List<TodoItem> items = new List<TodoItem>();
public MainWindow()
{
InitializeComponent();
items.Add(new TodoItem() { Username = "Eric", Completion = 45 });
items.Add(new TodoItem() { Username = "Maxwell", Completion = 80 });
items.Add(new TodoItem() { Username = "Sarah", Completion = 60 });
icTodoList.ItemsSource = items;
}
}
Mainwindows XAML:
<Window x:Class="itemcontrole_lesson.MainWindow"
xmlns:local="clr-namespace:itemcontrole_lesson"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ItemsControl x:Name="icTodoList">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type local:UserControl1}">
<local:UserControl1 />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</Window>
then a simple UserControle:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace itemcontrole_lesson
{
/// <summary>
/// Interaction logic for UserControl1.xaml
/// </summary>
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
//String CurentUserName = ????????
//Int Progress = ????????
}
private void Button_Click(object sender, RoutedEventArgs e)
{
///hows to remove the user from items in main windows??
}
}
}
UserControle XAML
<UserControl x:Class="itemcontrole_lesson.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="54.181" Width="399.331">
<Grid Margin="0,0,-155,0">
<Label Content="{Binding Username}" HorizontalAlignment="Left" Margin="23,23,0,0" VerticalAlignment="Top"/>
<Button Content="Close this UC" HorizontalAlignment="Left" Margin="414,22,0,0" VerticalAlignment="Top" Width="119" Click="Button_Click"/>
<ProgressBar HorizontalAlignment="Left" Value="{Binding Completion}" Height="10" Margin="204,23,0,0" VerticalAlignment="Top" Width="154"/>
</Grid>
</UserControl>
Pressing F5 everything will bind ok if you test.
But! how I'm supposed to retrieve my variable value in my usercontrole code?
see where I put comment in UC.
1- I need at least to find a way to remove this control from UI and from Items list?.
2-I'd like access username in my control and set it into a var
any suggestion?
Solution 1:
Use Tag property of button like below:
<Button Content="Close this UC" HorizontalAlignment="Left" Margin="414,22,0,0"
VerticalAlignment="Top" Width="119" Click="Button_Click" Tag="{Binding RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" />
Event handler:
private void Button_Click(object sender, RoutedEventArgs e)
{
var button = sender as Button;
List<object> list = (button.Tag as ItemsControl).ItemsSource.OfType<TodoItem>().ToList<object>();
list.Remove(button.DataContext);
(button.Tag as ItemsControl).ItemsSource = list;
}
Solution 2:
More elegant solution:
Create this Style in your MainWindow:
<Window.Resources>
<Style TargetType="Button">
<EventSetter Event="Click" Handler="Button_Click"/>
</Style>
</Window.Resources>
So now the Handler of any Button Click event is in the MainWindow.xaml.cs.
Then change handler definition like below:
private void Button_Click(object sender, RoutedEventArgs e)
{
var button = sender as Button;
items.Remove(button.DataContext as TodoItem);
icTodoList.ItemsSource = null;
icTodoList.ItemsSource = items;
}

OxyPlot PlotController

I am trying to disable auto panning on right button.
using OxyPlot;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using OxyPlot.Wpf;
using PlotController.Properties;
namespace PlotController
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
///
public class Chart
{
private OxyPlot.Series.LineSeries LS;
public PlotModel PlotModel {get;set;}
public Chart()
{
Random rnd = new Random();
PlotModel = new PlotModel();
LS = new OxyPlot.Series.LineSeries();
for (int i=0;i<100;i++)
{
LS.Points.Add(new DataPoint(i, rnd.Next(1,10)));
}
PlotModel.Series.Add(LS);
}
}
public partial class MainWindow : Window
{
Chart TChart;
public MainWindow()
{
TChart = new Chart();
OxyPlot.PlotController MyControl = new OxyPlot.PlotController();
MyControl.UnbindAll();
TestView = new PlotView();
TestView.Model = TChart.PlotModel;
TestView.Controller=MyControl;
DataContext = TChart;
InitializeComponent();
}
}
}
And xaml
* *
<Window x:Class="PlotController.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:oxy="http://oxyplot.org/wpf"
Title="MainWindow" Height="350" Width="525">
<Grid>
<oxy:PlotView Name="TestView" Model="{Binding PlotModel}" DefaultTrackerTemplate="{x:Null}" ></oxy:PlotView>
</Grid>
After unbinding all PlotCommand it still working.Why? How possible to disable panning on right button and enable on left button?
Try this in your MainWindow initialization code:
TestView.ActualController.UnbindAll();
TestView is the name of your PlotView defined in XAML.

The name "X" does not exist in the namespace "clr-namespace:Y"

I am trying to create a simple GUI application which changes the value of a string when it is changed in the GUI interface. The cs code is as follows:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace TryBinding
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
consle myconsole = new consle();
}
public class consle
{
public string mainstr {get; set;}
private int change = 23;
public void consle()
{
}
public void wrStr()
{
change = 44;
}
}
}
and the XAML code is as follows:
<Window x:Class="TryBinding.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TryBinding"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:consle x:Name="Data" mainstr="maintry"/>
</Window.DataContext>
<Grid>
<Button Content="Button" HorizontalAlignment="Left" Margin="244,37,0,0" VerticalAlignment="Top" Width="75"/>
<TextBlock HorizontalAlignment="Left" Margin="131,43,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Text="{Binding Path=mainstr}" />
<CheckBox x:Name="ok" Content="CheckBox" HorizontalAlignment="Left" Margin="131,76,0,0" VerticalAlignment="Top"/>
</Grid>
but I am getting the error:
Error 1 The name "consle" does not exist in the namespace "clr-namespace:TryBinding".
Error 2 'consle': member names cannot be the same as their enclosing type
I am not able to understand why its happening since the class consle exists in the namespace, and the consle() is a constructor.
your constructor shoule look like
public consle()
{
}
Constructor doesn't have the datatype.

Using an object in code, which is instantiated in xaml

I am trying to experiment making simple GUI application.
In it I have made a simple class called consle. I am using a button click to trigger an event Button_Click_1. This should in turn call the function wrStr which changes the value of variable change internally. This changed value should reflect in the GUI because the variable change is also bound in the XAML code.
The problem is, I do not know how to access the consle type object instantiated in XAML code. If I get the name of the object instantiated in XAML I could just say <NameOfObject>.wrStr() inside the Button_Click_1 function.
The XAML code is given below:
<Window x:Class="TryBinding.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TryBinding"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Button Content="Set44" HorizontalAlignment="Left" Margin="244,37,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click_1"/>
<TextBlock HorizontalAlignment="Left" Margin="339,76,0,0" TextWrapping="Wrap" Text="{Binding Source=consle, Path=change, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top"/>
</Grid>
The cs code is as follows:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace TryBinding
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
}
}
public class consle
{
public string mainstr {get; set;}
public int change { get; set; }
public consle()
{
}
public void wrStr()
{
change = 44;
}
}
}

List<string> is not updated back to ListBox's ItemsSource?

I'm new to WPF. I have a List<string> as a source for my ListBox's ItemsSource. Initially, the ListBox shows all the Items in my List<string> OK. However, after trying adding some string to my List<string>, the ListBox doesn't update the changes. I'm using Binding to bind the data (behind) with the ListBox (view), here is my code:
//Code behind
public MainWindow: Window {
public MainWindow(){
InitializeComponent();
Items = new List<string>(){"1","2","3"};//after loaded, all these values are displayed OK in my ListBox.
DataContext = this;
//Try clicking on a button to add new value
button1.Click += (s,e) => {
Items.Add("4");//But my ListBox stays the same without any update/changes.
};
}
public List<string> Items {get;set;}
}
//XAML
<ListBox ItemsSource={Binding Items}/>
Could you please point out what I'm doing wrong here and give me a solution? Thank you very much in advance.
If you had read the documentation of ItemsSource you would already know what is wrong.
[...]
This example shows how to create and bind to a collection that derives from the ObservableCollection<T> class, which is a collection class that provides notifications when items get added or removed.
you should try ObservableCollection instead because it's
Represents a dynamic data collection that provides notifications when items get added, removed, or when the whole list is refreshed.
<Window x:Class="WpfApplication3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Button Click="Button_Click" Content="Button" HorizontalAlignment="Left" Margin="441,289,0,0" VerticalAlignment="Top" Width="75"/>
<ListBox HorizontalAlignment="Left" ItemsSource="{Binding MyList,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Name="lstbox" Height="296" Margin="21,23,0,0" VerticalAlignment="Top" Width="209"/>
</Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApplication3
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private ObservableCollection<string> _myList = new ObservableCollection<string>(new List<string>(){"1","2","3"});
int i = 3;
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
MyList.Add(i++.ToString());
}
public ObservableCollection<string> MyList
{
get { return _myList; }
set { _myList = value; }
}
}
}

Categories

Resources