WPF ListView items binding to each other - c#

I have a listview in WPF which holds an observable collection of objects.
The objects are simple rectangular boxes containing a set of radio buttons:
The two sets of radio buttons are kept separate by setting the 'GroupName' in xaml to either GroupName="Numbers" or GroupName="Letters"
--EDIT--
As requested, here is the code within MyObject for the radiobuttons:
<RadioButton Grid.Column="1" Grid.Row="1" GroupName="Numbers" IsChecked="{Binding IsOne, Mode=TwoWay}" />
<RadioButton Grid.Column="2" Grid.Row="1" GroupName="Numbers" IsChecked="{Binding IsOne, Converter={StaticResource NegateBoolConverter}, Mode=TwoWay}" />
<RadioButton Grid.Column="1" Grid.Row="2" GroupName="Letters" IsChecked="{Binding IsA, Mode=TwoWay}" />
<RadioButton Grid.Column="2" Grid.Row="2" GroupName="Letters" IsChecked="{Binding IsA, Converter={StaticResource NegateBoolConverter}, Mode=TwoWay}" />
Negate bool converter simply returns the inverse of the bool value.
--End Edit--
The problem comes when I have a list of two of these objects in my list view. The first object (object 1) for example has 'One' and 'A' selected.
If I then select 'B' in object 2, the selection will try and change for object 1 as well (which messes everything up)
Here is an example of what I am hoping to achieve:
Has anyone seen this behaviour? On winforms it's fixed by setting a new BindingContext for each item but I don't know whether this is the same in WPF.
I am working in a fully MVVM environment, here is the code for the listview:
<ListView Name="ObjectsListView" ItemsSource="{Binding MyObjectList}" SelectedItem="{Binding SelectedObject, Mode=TwoWay}">
<ListView.ItemTemplate>
<DataTemplate>
<ContentControl>
<local:MyObject DataContext="{Binding}"/>
</ContentControl>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Please can someone let me know how to achieve separate behaviour in my listview items?
Thank you in advance.

Problem is that each item of listview creates radiobutton which the same GroupName, in wpf it is only possible to select one radiobutton from group.
So if you got two items ore more the radiobuttons will belong to one common Group.
Solution:
I add two new properties to Model (your class of SelectObject)
private string _NameFirst;
public string NameFirst
{
get { return _NameFirst; }
set
{
if (value != _NameFirst)
{
_NameFirst = value;
NotifyPropertyChanged();
}
}
}
private string _NameSecond;
public string NameSecond
{
get { return _NameSecond; }
set
{
if (value != _NameSecond)
{
_NameSecond = value;
NotifyPropertyChanged();
}
}
}
Each model item of the list should have different NameFirst and NameSecond, there are multiple ways to do so. E.g item1 : (NameFirst="A1",NameSecond="B1"), item2 : (NameFirst="A2", NameSecond="B2".
Also I modify the ContentControl of ListView I modified to StackPanel only for simplicity, you can stay with grid as well.
<StackPanel>
<RadioButton Grid.Column="0" Content="One" Grid.Row="0" GroupName="{Binding NameFirst}" IsChecked="{Binding IsOne, Mode=TwoWay}" />
<RadioButton Content="Two" GroupName="{Binding NameFirst}" IsChecked="{Binding IsOne, Converter={StaticResource NegateBoolConverter}, Mode=TwoWay}" />
<RadioButton Content="A" GroupName="{Binding NameSecond}" IsChecked="{Binding IsA, Mode=TwoWay}" />
<RadioButton Content="B" GroupName="{Binding NameSecond}" IsChecked="{Binding IsA, Converter={StaticResource NegateBoolConverter}, Mode=TwoWay}" />
</StackPanel>

Related

Radio buttons - showing two diff list with data in the view WPF

I have some code in the view:
<StackPanel Orientation="Horizontal" Background="{StaticResource GrayBrush8}">
<RadioButton Content="Radio1" />
<RadioButton Content="Radio2" />
</StackPanel>
<ct:DynamicFilterPanel Grid.Row="1"
ItemsType="{x:Type db:RadioData1}"
DbContext="{Binding DataContext}"
FilterQuery="{Binding FilterQuery, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
ChildCollectionsFilters="{Binding SubTypesFilter}"
WindowType="{x:Type mah:MetroWindow}"
/>
<ct:BDataGrid Grid.Row="2" IsReadOnly="True" ItemsSource="{Binding Model.List}" SelectedItem="{Binding Model.SelectedItem}" />
And I have some class with data and name of columns, models and viewmodels.
When I start the app it shows columns with data of RadioData1. Ok. And the first radiobutton is for that. But how can I do when I click second radio button it shows another list with columns from RadioData2. What kind of converter? Or changes I have to make in this view.
you must edit XAML
<StackPanel Orientation="Horizontal" Background="{StaticResource GrayBrush8}">
<RadioButton Name="Radio1" Content="Radio1" DataContextChanged="RadioButton_DataContextChanged" />
<RadioButton Name="Radio2" Content="Radio2" />
</StackPanel>
and in CS File
add method
private void RadioButton_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (Radio1.IsChecked==true)
{
//your Code
}
else
{
//your other code
}
}
and u can Use visibility for show or hide Something in XAML
<Button Name="btn1" Visibility="Hidden" />
and Use in your CS file like this
if (Radio1.IsChecked==true)
{
btn1.Visibility = Visibility.Visible;
}

Listbox selection change not firing on click on child in list box item

I have a wpf user control which contains a Listbox which is binded to my View Model. Each Listbox item is consists of three textblock. I made the UI in a way that when user clicks on the Frist TextBlock(Title) function in my View Model will get called.
To uniquely Identify the ListBox item corresponding to which text block now got clicked. I added another property in my view model which is bindied to SelectionChanged Event in the Listbox. So whenever my TextBlock binded command get exectuted I will use my SelectionChanged Property to find which List Box Item and use its data context.
But the issue I am facing now is that when User clicks on the First textblock, selectionchanged event is not firing. When User clicks outside the First Textblock only Selection Changed event is getting fired. Which made my view model to process wrong list box items.
Following is the XAML snippet.
<ListBox ScrollViewer.CanContentScroll="False" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Auto" SelectedItem="{Binding SelectedNotificationItem}" ItemsSource="{Binding MyArray}" BorderThickness="0" Margin="0, 0, 0, 0" ItemContainerStyle="{StaticResource HoverBackgroundStyle}" Name="NotificationListBox" >
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Border BorderThickness="4,0,0,0" BorderBrush="{Binding ColorThing, Converter={StaticResource SeverityToColorConverter} }" Margin="0, 0, 0, 0">
<StackPanel Margin="8, 0" Orientation="Vertical">
<TextBlock Style="{StaticResource HoverUnderlineStyle}" FontWeight="Bold" TextTrimming="CharacterEllipsis" Name="Title" Text="{Binding Title}" TextWrapping="WrapWithOverflow" Margin="0,4,0,0" >
<TextBlock.InputBindings>
<MouseBinding MouseAction="LeftClick" Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.ClickTitleCommand}"></MouseBinding>
</TextBlock.InputBindings>
</TextBlock>
<TextBlock FontWeight="Normal" Name="Desc" Text="{Binding Description}" TextWrapping="WrapWithOverflow">
</TextBlock>
<TextBlock FontWeight="Normal" Foreground="Gray" Name="Date" Text="{Binding CreationTime, StringFormat={}{0:ddd MM.dd.yyyy} }" Margin="0,4,0,4">
</TextBlock>
</StackPanel>
</Border>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Could you try changing your XAML to SelectedItem="{Binding SelectedNotificationItem, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Change the ListBox into an ItemsControl and change the orientation to horizontal

Textbox not updating

Ive tried searching, but maybe im not using the right terms to search for.
I have several textboxes that im using, and when i enter data, i see the values being updated when debugging, but they never get updated to the form.
Basically, I have a form that is used for the visuals, and then i have a class that handles all the activity. I have created the class as a resource, and I am referencing to the resource within the textboxes.
The only way that i really knew how to handle the updating of the forms was by implementing the calculations on values changing. So if I updated a property, I called the method from OnPropertyChanged(). This created issues because the values were always getting changed due to the calculations rewriting values. I then tried evaluating the changes of the new value
I.E.
public double In1
{
get{_return _in1;}
set{
if (_in1 != value)
_in1 = value;
OnPropertyChanged("In1");
}
}
regardless of anything, my problem is that i dont see the values getting written to the textbox. This is my first real endevour of using data binding so im assuming that im doing something incorrectly (clearly)
<ad:DockableContent
xmlns="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="DMC_Robot_Editor.GUI.frmAngleConvertor"
Title="frmAngleConvertor" Height="259" Width="282">
<ad:DockableContent.Resources>
<local:AngleConvertor x:Key="Converter"/>
</ad:DockableContent.Resources>
<Grid >
<GroupBox HorizontalAlignment="Stretch" VerticalAlignment="Top">
<Grid>
<ComboBox x:Name="cbInput" HorizontalAlignment="Stretch" VerticalAlignment="Top" Grid.Column="1" Grid.ColumnSpan="3" Grid.Row="1" DisplayMemberPath="ValueCartesianString" SelectedValuePath="ValueCartesianEnum" IsSynchronizedWithCurrentItem="True" SelectedIndex="{Binding InputItem,Source={StaticResource Converter}}" ItemsSource="{Binding InputConvention, Source={StaticResource Converter}}" IsReadOnly="True"/>
<TextBox x:Name="tbIn1" HorizontalAlignment="Center" VerticalAlignment="Bottom" Text="{Binding In1, Converter={StaticResource DoubleToStringConverter}, Source={StaticResource Converter}}" Grid.Column="0" d:LayoutOverrides="GridBox" Grid.Row="2" Width="50" TextAlignment="Center">
<TextBox.DataContext>
<local:AngleConvertor/>
</TextBox.DataContext> </Grid>
</ad:DockableContent>
public class AngleConverter()
{
private double _in1 = 0.0;
public double In1
{
get{_return _in1;}
set{
if (_in1 != value)
_in1 = value;
OnPropertyChanged("In1");
}
}
}
Try to apply UpdateSourceTrigger=PropertyChanged on your text box:
Text="{Binding Path-In1, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource DoubleToStringConverter}, Source={StaticResource Converter}}"
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
You can add to your binding UpdateSourceTrigger=PropertyChanged with your Mode TwoWay
<TextBox Name="tbIn1"
HorizontalAlignment="Center"
VerticalAlignment="Bottom"
Text="{Binding In1, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged,
Converter={StaticResource DoubleToStringConverter},
Source={StaticResource Converter}}"
Grid.Column="0"
d:LayoutOverrides="GridBox"
Grid.Row="2"
Width="50"
TextAlignment="Center"
/>
your real code should have something like this:
public class AngleConverter : INotifyPropertyChanged
so i assume its just a typo in your code. you did not post your converter code, the binding in your textbox is ok. Textbox default UpdateSourceTrigger is lostfocus. so maybe UpdateSourceTrigger=PropertyChanged did what you want.
Review the binding
Does DoubleToStringConverter get called?
Is get called?
Text="{Binding In1, Converter={StaticResource DoubleToStringConverter}, Source={StaticResource Converter}}"
Move Source out of binding in into DataContext on the DockableContent.
DataContext="{Binding RelativeSource={RelativeSource self}}"
Try with no converter
Text="{Binding In1}"

Trying to get IsEnabled to bind to Dependency Property

Any idea where I'm going wrong with this code. I want the TextBox to be Enabled when the associated RadioButton for it is selected, and then when a different radio button is selected I want it to be Enabled=False. I created a ProxyMode dependency property and have changed the getter to obtain it's bool value based on whether Proxy is selected or not. Doesn't seem to work...any ideas?
// Proxy Host Name
public string Proxy
{
get { return (string)GetValue(ProxyProperty); }
set { SetValue(ProxyProperty, value); }
}
public static readonly DependencyProperty ProxyProperty =
DependencyProperty.Register("Proxy", typeof(string), typeof(ConfigWindowViewModel), new UIPropertyMetadata("[e.g. proxy.mycompany.com]"));
public bool ProxyMode
{
get { return Proxy == "Proxy"; }
set { SetValue(ProxyModeProperty, value); }
}
public static readonly DependencyProperty ProxyModeProperty =
DependencyProperty.Register("ProxyMode", typeof(bool), typeof(ConfigWindowViewModel));
And the XAML
<StackPanel Grid.Column="0" Margin="2">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<RadioButton IsChecked="{Binding Path=Mode, Converter={StaticResource enumBooleanConverter}, ConverterParameter=Proxy}"
VerticalAlignment="Center"
Padding="2,0,10,0">Proxy
</RadioButton>
<TextBox Text="{Binding Path=Proxy}"
IsEnabled="{Binding Path=ProxyMode}"
Width="Auto"
Name="ProxyHostTextBox"
VerticalAlignment="Center"
MinWidth="150"
/>
</StackPanel>
<RadioButton IsChecked="{Binding Path=Mode, Converter={StaticResource enumBooleanConverter}, ConverterParameter=Direct}">Direct</RadioButton>
</StackPanel>
The easiest way to enable/disable the textbox based on whether the proxy RadioButton is checked is to bind the IsEnabled property of the TextBox directly to the IsChecked property of the proxy RadioButton. Assuming the proxy RadioButton is named "proxy":
<TextBox Text="{Binding Path=Proxy}" IsEnabled="{Binding ElementName=proxy, Path=IsChecked}"/>
If you meant for your RadioButton controls to be linked so that only one can be selected at once, you need to set the GroupName property to something on both of them (it should be the same for all linked RadioButton controls).
Let me know if you have further questions.
As with the second version of this question:
<RadioButton x:Name="RadioButton2" />
<TextBox IsEnabled="{Binding IsChecked, ElementName=RadioButton2}" />
think I came up with a better way to do this - so the question probably isn't a good one to ask - the following without dependency property seem ok
<StackPanel Grid.Column="0" Margin="2">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<RadioButton IsChecked="{Binding Path=Mode, Converter={StaticResource enumBooleanConverter}, ConverterParameter=Proxy}" VerticalAlignment="Center" Padding="2,0,10,0" Name="ProxyModeRadioButton">Proxy</RadioButton>
<TextBox Text="{Binding Path=Proxy}"
IsEnabled="{Binding ElementName=ProxyModeRadioButton, Path=IsChecked}"
Width="Auto" Name="ProxyHostTextBox" VerticalAlignment="Center" MinWidth="150"
/>
</StackPanel>
<RadioButton IsChecked="{Binding Path=Mode, Converter={StaticResource enumBooleanConverter}, ConverterParameter=Direct}">Direct</RadioButton>
</StackPanel>

WPF: How to select parent listbox if user clicked on child listbox

In my application using DataTemplate mechanism I insert into ListBox item another listbox. But is it possible that when selected one listboxitem in parent listbox, the focus may be on another parent listboxitem's child (see picture)
How to do: if one of child listbox in focus (one item from them selected), then parent listboxitem being selected to? Using binding or templating
<DataTemplate x:Key="NotesListBoxDataTemplate" DataType="Note">
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<TextBox Text="{Binding Path=Title, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBox>
<my:DatePicker Height="25" Name="datePicker1" Width="115" xmlns:my="clr-namespace:Microsoft.Windows.Controls;assembly=WPFToolkit"
SelectedDate="{Binding LastEdit,
Mode = TwoWay}" />
</StackPanel>
<TextBox Text="{Binding Path=Content, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBox>
<StackPanel Orientation="Horizontal">
<ListBox Name="ImagesListBox" SelectedIndex="{Binding Mode=OneWayToSource, Source={StaticResource progParameters}, Path=SelectedImage, UpdateSourceTrigger=PropertyChanged}" ItemsSource="{Binding Path=Images}" ItemTemplate="{StaticResource NotesListBoxImagesTemplate}" Style="{StaticResource HorizontalListBox}">
</ListBox>
<StackPanel Orientation="Vertical">
<Button Name="AddImageButon" Content="+" Click="AddImageButon_Click"></Button>
<Button Name="RemoveImageButon" Content="-" Click="RemoveImageButon_Click"></Button>
</StackPanel>
</StackPanel>
</StackPanel>
</DataTemplate>
On the parent ListBox set property IsSynchronizedWithCurrentItem to true, then in the inner ListBoxes set the SelectedItem property to "{Binding SelectedItem ElementName=lbParent}".
Consider using a Converter to help you get specific data that is not accessible thru xaml or if you need to do some caculations.
Hope this helps.

Categories

Resources