I have a function (Called OpenExcel())that opens an excel document and reads its values.
For the function to know what excel document to open, a string value must be provided. But in MVVM application with a barcode reader, the function will execute before the property has its value assigned. (I have tried with UpdateSourceTrigger=PropertyChanged in the Binding with no luck.)
I ended up using the PreviewTextInput Event of the TextBox, to manually assign to the property (which works).
My issue is that when I call the function from code-behind, the List in the View does not update with the values. (I have stepped through the function and checked that there are values there). However, when I call the function through Prism's ICommand, the list displays all the values.
All Relevant Code:
XAML:
<TextBox Text="{Binding Serial,Mode=TwoWay}" x:Name="serial_txt" PreviewKeyDown="serial_txt_PreviewKeyDown" PreviewTextInput="serial_txt_PreviewTextInput" />
<Button Command="{Binding GetFollower}"/>
<ListView ItemsSource="{Binding Parts}"/>
CodeBehind:
public ListViewModel view;
public LCMList()
{
InitializeComponent();
view = new ListViewModel();
}
private void serial_txt_PreviewKeyDown(object sender, KeyEventArgs e)
{
if(e.Key == Key.Enter) //scanned string is always followed by Enter input.
{
view.OpenExcel(sender); //Fails if called from here
}
}
private void serial_txt_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
view.Serial += e.Text;
}
ListViewModel:
public ICommand GetFollower
{
get { return new DelegateCommand<object>(OpenExcel); } //Succeeds if called from here
}
private string serial;
public string Serial
{
get { return serial; }
set
{
serial = value;
OnPropertyChanged("Serial");
}
}
private ObservableCollection<Part> parts;
public ObservableCollection<Part> Parts
{
get { return parts; }
set
{
parts = value;
SetProperty(ref parts, value);
OnPropertyChanged("Parts");
}
}
public void OpenExcel(object obj)
{
/* Find Excel document and read the applicable fields and put into partslist.
Needs Serial property as reference */
Parts = partslist;
}
The Parts property gets its values written to, but the list in View stays empty.
In Conclusion:
function updates the properties properly when called through prism and DelegateCommand, but not when called from CodeBehind.
instead of this
public LCMList()
{
InitializeComponent();
view = DataCotnex;
}
private void serial_txt_PreviewKeyDown(object sender, KeyEventArgs e)
{
if(e.Key == Key.Enter) //scanned string is always followed by Enter input.
{
view.OpenExcel(sender); //Fails if called from here
}
}
you can try that
private void serial_txt_PreviewKeyDown(object sender, KeyEventArgs e)
{
if(e.Key == Key.Enter) //scanned string is always followed by Enter input.
{
if (!(DataContext is ListViewModel vm)) return;
vm.OpenExcel(sender);
}
}
also don't forget to add datacontext in XAML
<Window.DataContext>
<local:ListViewModel />
</Window.DataContext>
Related
EDIT: I have updated this with the two methods recommended
I am writing a simple custom PI (OSISoft) data viewer. I have two classes, one for the UI and one for the PI server interactions/program logic. The property for the data to be displayed has an event that fires when the property is changed. How do I get that change to propagate over to the UI class so the associated text box will automatically refresh?
Original code:
namespace PIViewer {
public partial class MainWindow : Window
{
ProgLogic logic;
public MainWindow() {
InitializeComponent();
logic = new ProgLogic();
InitializeValues();
}
private void InitializeValues() {
logic.SomeValue = logic.GetValFromServer(valueTag);
}
private void TextBoxSomeValue(object sender, TextChangedEventArgs e) {
// ??? something happens here?
}
}
public class ProgLogic {
private int someValue;
public event System.EventHandler SomeValueChanged;
protected void OnSomeValueChanged()
{
SomeValueChanged?.Invoke(this, EventHandlerArgs e);
}
public int SomeValue {
get => someValue;
set {
someValue = value;
OnSomeValueChanged();
}
}
public int GetValFromServer(string valueTag) {
int piValue;
piValue = PISDKMethodToGetServerValue(valueTag);
return piValue;
}
}
}
Method 1: Events
namespace PIViewer {
public partial class MainWindow : Window
{
ProgLogic logic;
public MainWindow() {
InitializeComponent();
logic = new ProgLogic();
logic.SomeValueChanged += Logic_SomeValueChanged;
InitializeValues();
}
private void Logic_SomeValueChanged(int obj) {
TextBoxSomeValue.Text = obj.toString();
}
private void InitializeValues() {
logic.SomeValue = logic.GetValFromServer(valueTag);
}
private void TextBoxSomeValue_TextChanged(object sender, TextChangedEventArgs e) {
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) {
logic.SomeValueChanged -= Logic_SomeValueChanged;
}
}
public class ProgLogic {
private int someValue;
public event Action<int> SomeValueChanged;
public virtual void OnSomeValueChanged(int newValue) {
SomeValueChanged?.Invoke(newValue);
}
public int SomeValue {
get => someValue;
set {
someValue = value;
OnSomeValueChanged(value);
}
}
public int GetValFromServer(string valueTag) {
int piValue;
piValue = PISDKMethodToGetServerValue(valueTag);
return piValue;
}
}
}
Method 2: MVVM pattern
MainWindow.xaml:
<Window
Closing="Window_Closing"
Title="My App">
<TextBox x:name="TextBoxSomeValue" text="{binding SomeValue, UpdateSourceTrigger=PropertyChanged}" />
</Window>
The important part here is the binding parameter in the text field of the TextBox definition, which points to the PropertyChangedEventHandler.
C# code:
namespace PIViewer {
public partial class MainWindow : Window
{
ProgLogic logic;
public MainWindow() {
InitializeComponent();
logic = new ProgLogic();
InitializeValues();
}
private void InitializeValues() {
logic.SomeValue = logic.GetValFromServer(valueTag);
}
private void TextBoxSomeValue_TextChanged(object sender, TextChangedEventArgs e) {
// run some other code when the text box updates
}
}
public class ProgLogic : INotifyPropertyChanged {
private int someValue;
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChange(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public int SomeValue {
get => someValue;
set {
someValue = value;
OnPropertyChange("SomeValue")
}
}
public int GetValFromServer(string valueTag) {
int piValue;
piValue = PISDKMethodToGetServerValue(valueTag);
return piValue;
}
}
}
ProgLogic now implements INotifyPropertyChanged, which notifies the View of property changes, so that Bindings are updated.
I see you are heading the right way with C# event system. One thing I would change is event type from System.EventHandler to System.Action<int>. Even though people tend to propagate extending System.EventArgs class and writing custom delegates for handling events, using System.Action<T> is much easier to grasp for beginner.
So let's go with System.Action<int> example now. First, let's change ProgLogic class to be more like this:
public class ProgLogic
{
public event Action<int> SomeValueChanged;
//
// your other code goes here
//
private void OnSomeValueChanged(int newValue)
{
SomeValueChanged?.Invoke(newValue);
}
}
Now, you need to subscribe to the earlier written event in MainWindow class. So we do that as early as possible - in the constructor of MainWindow:
public MainWindow()
{
InitializeComponent();
logic = new ProgLogic();
logic.SomeValueChanged += OnSomeValueChanged;
InitializeValues();
}
Then, you describe your logic in the OnSomeValueChanged callback method, like:
private void OnSomeValueChanged(int newValue)
{
TextBoxSomeValue.text = newValue.ToString();
}
Make sure you unsubscribe from the event once MainWindow is getting destroyed to prevent memory leakage. This is just bare-bones for whole logic. I've left some space for interpretation. ;)
I'm not sure if I'm understanding the main point of your question but if you want to create a new value and have that value saved as the default value then you should create a string in your application setting and call on it on text changed.
At the top of your visual2019, in the menu options. open the debug menu and at the bottom you will see ("Your project name" + properties)
2.You will be brought into a new window with menu options on the left, go to the settings.
3.Create a string and set the value to "Some random text"
Note: In the example I placed one text box in front of the other, though this in not a great method it will prevent the text from appearing as a double or drawing a blank
Settings String Example
xaml
<Window x:Class="SaveNewText.MainWindow"
Title="MainWindow" Height="450" Width="800">
<Grid>
<TextBox x:Name="DefaultText" Height="250" Width="250"
Background="Transparent"
Foreground="Black" MouseDown="TextBlock_MouseDown" IsReadOnly="True"/>
<TextBox x:Name="NewText" Height="250" Width="250" Background="Transparent"
Foreground="Black" TextChanged="NewText_TextChanged"/>
</Grid>
</Window>
xaml.cs
namespace SaveNewText
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DefaultText.Text = Properties.Settings.Default.TextString;
}
private void TextBlock_MouseDown(object sender, MouseButtonEventArgs e)
{
NewText.Focus();
}
private void NewText_TextChanged(object sender, TextChangedEventArgs e)
{
Properties.Settings.Default.TextString = NewText.Text;
Properties.Settings.Default.Save();
DefaultText.Text = Properties.Settings.Default.TextString;
}
}
}
So I planning to bind label from two files or more, because I place the label and the cs file in separate way. For example:
SettingServicesPhone.xaml
<Label x:Name="sipLoginStatus"
Width="106"
Height="27"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Content="{Binding SipLoginStatusContent}"
FontSize="13" />
For the SettingServicePhone.xaml.cs I declared public String sipLoginStatusContent;
And I use Settings.xaml and Setting.xaml.cs as a container of all functions.
I've declared public static SettingsServicesPhone setCall = new SettingsServicesPhone(); on Setting.xaml.cs. And also write get set.
public String SipLoginStatusContent
{
get { return setCall.sipLoginStatusContent; }
set
{
if (setCall.sipLoginStatusContent != value)
{
setCall.sipLoginStatusContent = value;
OnPropertyChanged("SipLoginStatusContent"); // To notify when the property is changed
}
}
}
And here the example of onclick button that I stated on Settings.xaml.cs
public void applyBtn_Click(object sender, RoutedEventArgs e)
{
SipLoginStatusContent = "Logging In";
}
It's work fine if I included them in one file. But seems like it doesn't running if I make it separate. Am I doing it wrong way? Thank you.
Set the DataContext of the window where the Label is defined to an instance of the class where the SipLoginStatusContent property is defined:
public partial class Settings : Window
{
public static SettingsServicesPhone setCall = new SettingsServicesPhone();
public Settings()
{
InitializeComponent();
DataContext = this; //<--
}
public String SipLoginStatusContent
{
get { return setCall.sipLoginStatusContent; }
set
{
if (setCall.sipLoginStatusContent != value)
{
setCall.sipLoginStatusContent = value;
OnPropertyChanged("SipLoginStatusContent"); // To notify when the property is changed
}
}
}
public void applyBtn_Click(object sender, RoutedEventArgs e)
{
SipLoginStatusContent = "Logging In";
}
}
I'm trying to make some sort of wheel spinning. I have 5 customized text blocks, text file with the list of values (it may consist of 1-1000 items). After reading the file I have a 'List fileValues' with its values. I decided to create another 'List wheel' which will contain up to 5 elements at the time and is expected to be bind to text blocks.
When one presses a spin button, last element of 'wheel' is removed and new element from 'values' is added to the beginning of the 'wheel' list.
In order UI will be responsive to changes in the list, it is good to bind each element in the 'wheel' to corresponding text block on UI. But what I tried to do up to this moment didn't work.
Here is what I tried to do (the code is a little bit dirty, but I try to make it work firstly).
5 customized text blocks
<TextBlock Name="Value1" TextWrapping="WrapWithOverflow"/>
<TextBlock Name="Value2" TextWrapping="WrapWithOverflow"/>
<TextBlock Name="Value3" TextWrapping="WrapWithOverflow"/>
<TextBlock Name="Value4" TextWrapping="WrapWithOverflow"/>
<TextBlock Name="Value5" TextWrapping="WrapWithOverflow"/>
ObservableList which implements INotifyCollectionChanged interface
class ObservableList : INotifyCollectionChanged, IEnumerable
{
private readonly List<string> _valuesList;
public string First
{
get { return _valuesList.First(); }
}
public string Last
{
get { return _valuesList.Last(); }
}
public ObservableList()
{
this._valuesList = new List<string>();
}
public string this[Int32 index]
{
get
{
if (_valuesList.Count == 0 || index + 1 > _valuesList.Count)
{
return "------";
}
return _valuesList[index];
}
}
public void AddLast(string value)
{
_valuesList.Add(value);
OnNotifyCollectionChanged();
}
public void AddFirst(string value)
{
_valuesList.Insert(0, value);
OnNotifyCollectionChanged();
}
public void RemoveFirst()
{
_valuesList.RemoveAt(0);
OnNotifyCollectionChanged();
}
public void RemoveLast()
{
_valuesList.Remove(_valuesList.Last());
OnNotifyCollectionChanged();
}
public event NotifyCollectionChangedEventHandler CollectionChanged;
public void OnNotifyCollectionChanged()
{
if (CollectionChanged != null)
{
CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
}
public IEnumerator GetEnumerator()
{
return (_valuesList as IEnumerable).GetEnumerator();
}
}
XAML Code-behind
public partial class MainWindow : Window
{
private List<string> _values = new List<string>();
private ObservableList _uiValues = new ObservableList();
public MainWindow()
{
InitializeComponent();
Value1.DataContext = _uiValues[0];
Value2.DataContext = _uiValues[1];
Value3.DataContext = _uiValues[2];
Value4.DataContext = _uiValues[3];
Value5.DataContext = _uiValues[4];
}
private void LoadFileBtn_Click(object sender, RoutedEventArgs e)
{
//Loads text file and fills _values
}
private void SpinBtn_Click(object sender, RoutedEventArgs e)
{
InitUiTextBlocks();
//Spin simulation
}
private void InitUiTextBlocks()
{
_uiValues.Clear();
for (int i = 0; i < 5; ++i)
{
//Nothing appears on UI and CollectionChanged event is null
_uiValues.AddLast(_values.First());
_values.RemoveAt(0);
}
}
}
I tried to use 'ObservableCollection', but the effect is the same. Nothing appears on UI. In fact I can't imagine how to bind each of List element to specific Label. Is it even possible to do such binding?
In the XAML do something like:
<Label Name="some_name" Content="{Binding SomeStingProperty}"/>
and in the code behind, have a
public string SomeStringProperty {get; set;}
you can bind to a collection as well, and if it's an ObservableCollection it will update on change.
search for basic XAML binding otherwise :)
(on a side note, it's cleaner i think it the XAML, i personally don't like to do it in the code behind ...)
As a side note, and totally self promoting, here are 2 articles that will probably help:
Understanding selected value
The big mvvm template.
The second might be a bit over your head if you're a beginner, but should be worth reading nevertheless.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
What I want is to type in a textbox before I start my packet sniffer to only show me results that I want. This is what I have but it isn't working. I want this listview to just show port 3074 using a textbox does anyone know how to do this? This is a packet sniffer
(source: gyazo.com)
Anyone know how I can do that?
This is what I am using
namespace Network.Packet.Analyzer.App.Forms.Main
{
public partial class FrmAnalyzer : Form, IAnalyzer
{
public FormaAnalyzerPresenter _presenter;
public FrmAnalyzer()
{
InitializeComponent();
_presenter = new FormaAnalyzerPresenter(this);
}
//callled when ListView control selection being made
private void lstReceivedPackets_SelectedIndexChanged(object sender, EventArgs e)
{
_presenter.CreateDetailedTree();
}
//start button click event method
private void toolStripButton1_Click(object sender, EventArgs e)
{
_presenter.StartClicked();
}
//stop button click event method
private void tbtnStop_Click(object sender, EventArgs e)
{
_presenter.StopClicked();
}
private void Form1_Load(object sender, EventArgs e)
{
_presenter.ApplicationStarted();
}
// clear all button click event method
// clearing buffer,listvie control,and treeview
private void tbtnClearAll_Click(object sender, EventArgs e)
{
_presenter.ClearAllClicked();
}
private void closeToolStripMenuItem_Click(object sender, EventArgs e)
{
ApplicationClose();
}
private void menuAlwaysOnTop_Click(object sender, EventArgs e)
{
_presenter.TopMostClicked();
}
#region IAnalyzer Members
public ListView ListReceivedPackets
{
get { return lstReceivedPackets; }
}
public ListView ListOpenPorts
{
get
{
return lstOpenPorts;
}
}
public ProgressBar ProgressBufferusage
{
get { return progressBufferUsage; }
}
public TreeView TreePackedDetails
{
get { return treePacketDetails; }
}
public void SetTotalPacketReceivedText(string strNumber)
{
if (strNumber != null)
lblTotalPkgsReceived.Text = strNumber;
}
public void SetBufferUsage(string strNumber)
{
if (strNumber != null)
lblBufferUsage.Text = strNumber;
}
public void SetReadyText(string text)
{
if (text != null)
lblStripReady.Text = text;
}
public bool ButtonStartEnabled
{
get { return tbtnStar.Enabled; }
set { tbtnStar.Enabled = value; }
}
public bool ButtonStopEnabled
{
get { return tbtnStop.Enabled; }
set { tbtnStop.Enabled = value; }
}
public bool TopMostChecked
{
get
{
return topMostMenuItem.Checked;
}
set
{
topMostMenuItem.Checked = value;
}
}
public bool FormShowAsTopMost
{
get
{
return this.TopMost;
}
set
{
this.TopMost = value;
}
}
public void ApplicationClose()
{
this.Close();
}
public StartupInfo StartupInformation
{
get
{
return _presenter.StartupInformation;
}
set
{
_presenter.StartupInformation = value;
}
}
public void ShowErrorMessage(string message)
{
MessageBox.Show(message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
public void ShowWarningMessage(string message)
{
MessageBox.Show(message, "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
public void ShowDefaultErrorMessage()
{
MessageBox.Show("Unexpected error has acquired", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
public void ShowDefaultErrorMessage(Exception ex)
{
MessageBox.Show(String.Format("Unexpected error has acquired. Error message: {0}", ex.Message), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
public void ShowErrorMessage(string message, Exception ex)
{
MessageBox.Show(String.Format("{0}. Error message: {1}", message, ex.Message), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
public void Invoke(Action act)
{
this.Invoke(new MethodInvoker(delegate { act(); }));
}
private void button1_Click(object sender, EventArgs e)
{
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
}
}
}
#endregion
This is the other part: pastebin.com/rPWMJHCe
Okay, seeing your code from pastebin, i will keep my answer rather simple. My answer is most certainly not the best and not the most elegant, and you will certainly still hit a wall here and there, but making it better and easier to work with would most likely require abandoning ListView in favor of a more capable control (such as DataGridView, for example). Anyway...
For the example given below, i'll pick the ListView ListOpenPorts. But of course you can adapt this approach to other ListViews as well, just pay attention to keep track of where which data is stored inside the ListViewItems.
The basic idea of a filtered content display is something ListView doesn't really like. It is not so much the filtering itself, but the fact that all items must be somewhere when we change or switch off filtering. What makes ListView suck so much in this regard is that it insists to maintain the list of items internally instead of giving us the opportunity to control and swap that list easily (hence me pointing towards DataGridView earlier).
The approach involves maintaining another private list _listOpenPortItems in the class FrmAnalyzer which will keep all 'open port' ListViewItems. This is necessary so our code can access them and feed them back into the lstOpenPorts ListView whenever the filtering is switched off or changed.
private readonly List<ListViewItem> _listOpenPortItems = new List<ListViewItem>();
To always have the correct items in the _listOpenPortItems list requires to not access ListOpenPorts.Items directly. Instead, methods will be implemented in the class FrmAnalyzer which will realize equivalent functions for any function used on ListOpenPorts.Items before. Those methods manipulate the private list _listOpenPortItems and also add/remove items to/from the actual ListView control depending on the filter settings.
Also note the two properties IsPortFilterEnabled and PortToFilter, which control filtering and which i will explain a bit later.
public void AddOpenPortItem(ListViewItem openPortItem)
{
_listOpenPortItems.Add(openPortItem);
if (!IsPortFilterEnabled || PortToFilter == openPortItem.SubItems[3])
lstOpenPorts.Items.Add(openPortItem);
}
public void RemoveOpenPortItem(ListViewItem openPortItem)
{
_listOpenPortItems.Remove(openPortItem);
if (!IsPortFilterEnabled || PortToFilter == openPortItem.SubItems[3])
lstOpenPorts.Items.Remove(openPortItem);
}
//...Also implement here methods for all other functions of
//...ListOpenPorts.Items you used before (such as RemoveByKey, ContainsKey, etc...)
//...which will have to realize the equivalent function on _listOpenPortItems.
//...Any method which can potentially alter _listOpenPortItems will have to have a
//...code snippet like:
// if (!IsPortFilterEnabled || PortToFilter == openPortItem.SubItems[3])
// lstOpenPorts.Items.XXXXXX(openPortItem);
//
//...(where XXXXXX is the appropriate method of lstOpenPorts.Items)
(Note that i here assume the port number being the subitem with index 3.)
With those methods implemented, just replace all direct accesses of ListOpenPorts.Items with the respective method calls. For example:
_view.Invoke(() => _view.ListOpenPorts.Items.Remove(item));
would be replaced with:
_view.Invoke(() => _view.RemoveOpenPortItem(item));
This code change sound like difficult work, but it is actually not that hard and just a question of finding all usages of "ListOpenPorts"/"ListOpenPorts.Items" - a simple text search through your whole source code is the bigger part of the job.
To control the filter we will use the two properties i already mentioned: PortToFilter, a String property which will hold the port number to filter for; and IsPortFilterEnabled, a bool property denoting whether the filter is enabled or not.
Both properties are, like the methods above, implemented in the class FrmAnalyzer.
public bool IsPortFilterEnabled
{
get { return _isPortFilterEnabled; }
set
{
if (_isPortFilterEnabled != value)
{
_isPortFilterEnabled = value;
RefreshOpenPortListView();
}
}
}
private bool _isPortFilterEnabled = false;
public string PortToFilter
{
get { return _portToFilter ; }
set
{
//
// Note that setting PortToFilter will turn on the filter
//
if(!_isPortFilterEnabled || _portToFilter != value)
{
_portToFilter = value;
RefreshOpenPortListView();
}
}
}
private string _portToFilter = "0";
Remark: It would be better to handle port numbers as what they are - int numbers, not strings. But since you already use strings for port numbers, i chose the string data type here, too.
You might notice the calls of method RefreshOpenPortListView. This is a method which updates lstOpenPorts.Items according to the filter settings.
private void RefreshOpenPortListView()
{
//
// Note that this method does not preserve the current selection in the List View.
// If you need to preserve it, save the current selection here and restore it
// at the end of this method again.
//
IEnumerable<ListViewItem> itemsForListView =
(_isPortFilterEnabled) ?
_listOpenPortItems.Where(item => PortToFilter == item.SubItems[3])
: _listOpenPortItems;
lstOpenPorts.BeginUpdate();
_lstOpenPorts.Itmes.Clear();
foreach(ListViewItem item in _itemsForListView)
_lstOpenPorts.Add(openPortItem);
_lstOpenPorts.EndUpdate();
}
(Note that i here assume the port number being the subitem with index 3.)
Finally, how do you set IsPortFilterEnabled and PortToFilter? Here one idea briefly outlined, but there a numerous different ways of how to do that:
Let a checkbox toggle the value of IsPortFilterEnabled. This checkbox basically enables/disables the filtered view.
Let a (numerical) textbox dump its content into PortToFilter. This textbox contains the port number to filter for. Note that (according to my suggested implementation) whenever the textbox transfers its content to PortToFilter, the filtered view is enabled and updated.
You want to sort or filter?, your title says sort, but your description says "to just show those results"
If your Listview is bound to a DataTable, then you can filter or sort using the DefaultView property.
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (comboBox1.SelectedIndex == 0)
dtItems.DefaultView.Sort = "ID";
else
dtItems.DefaultView.Sort = "Name";
MyBindMethod(dtItems);
}
Or if you want to filter by ID
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
dtItems.DefaultView.RowFilter = "ID = '" + comboBox1.SelectedValue + "'";
MyBindMethod(dtItems);
}
Not sure if anyone can be of help here, but I have a comboxbox bound to a viewmodel property, on a form who's value is set by an event. It is working in house, but there is one client where the event fires, the value is set (I know because I added some logging), but their screen is not updated. I have a copy of the database, and I mirror the steps and it works. Any ideas why that could be happening? I included the code below, but it is pretty basic.
private void ViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "TriggerId")
{
Method();
}
}
private void Method()
{
ComboBoxSelectedProperty = null;
if (TriggerId != null)
{
var object = Work.ObjectStore.GetById((int)TriggerId);
if (object != null)
{
ComboBoxSelectedProperty = Work.AssociatedObjectStore.GetByObjenct(object);
}
NotifyPropertyChanged("ComboboxSourceSource");
}
}
}