0

I want to change the color of a button in a popup based on certain conditions and I want to set some text based on those conditions. I need to do this in the code behind.

I have a popup with several TextBlocks in a StackPanel. The first 3 are bound to details about the course (this is a scheduling app; school project). The last one I want to be empty unless there is a conflict concerning that course. That is, I want to dynamically decide what, if anything, goes in the TextBlock each time the popup is opened.

    <Popup Name="CourseListDetail" Width="Auto" Height="Auto">
            <StackPanel>
                <TextBlock Margin="10,10,10,0">
                    <TextBlock.Text>
                        <MultiBinding StringFormat="{}{0}: {1}">
                            <Binding Path="CourseCode"/>
                            <Binding Path="LongTitle"/>
                        </MultiBinding>
                    </TextBlock.Text>
                </TextBlock>
                <TextBlock Margin="10,0,10,0">
                    <TextBlock.Text>
                        <MultiBinding StringFormat="{}{0} - {1}/{2}">
                            <Binding Path="ProfessorsString"/>
                            <Binding Path="Enrollment"/>
                            <Binding Path="Capacity"/>
                        </MultiBinding>
                    </TextBlock.Text>
                </TextBlock>
                <TextBlock Margin="10,0,10,0" Grid.Row="2" Grid.Column="1" Text="{Binding MeetingsString}" TextWrapping="Wrap"
                           HorizontalAlignment="Center"/>
                <TextBlock TextWrapping="WrapWithOverflow"  MaxWidth="300" Text="{Binding Description}" Margin="10,10,10,10"/>
                <TextBlock Name="ConflictText" Foreground="Red" HorizontalAlignment="Center" Text="{Binding ConflictString}"/>
                <Button Name="Detail_AddCourse" Content="Add To Schedule" Margin="10,10,10,10" Padding="5" Background="LightGreen"
                        Click="AddCourseButton_Click"
                        Style="{StaticResource MyButtonStyle}"/>
            </StackPanel>
        </Border>
    </Popup>

I have a function that opens the popup when you click on a course and that gives the popup the DataContext about the course, but I don't know how to access the TextBlock, or the button immediately below it, through the function. I figured there'd be a child property or something so I could call the button, something like:

CourseListDetail.Detail_AddCourse.Background = "Red";

or

CourseListDetail.Child.Button().Background = "Red";

etc.

Code behind function:

    private void CourseListItem_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        ListViewItem selection = sender as ListViewItem;
        Course course = selection.DataContext as Course;

        CourseListDetail.DataContext = course;
        CourseListDetail.PlacementTarget = selection;
        CourseListDetail.IsOpen = true;
        CourseListDetail.Focus();

        hasConflict conflictType = _schedule.HasConflict(course);
        if (conflictType != hasConflict.NO_CONFLICT) {     //If there is a conflict
            //Change button color to red here

            if (conflictType == hasConflict.COURSE_FULL) { //If the course is full
                //Set TextBlock text to conflict message here
            }
        }
        else { //No conflict
            //Set button color to green
        }
    } 

hasConflict is just an enum

  • 1
    Why don't you just use some properties and bind them to color or anything else ? – Krishna Apr 26 '17 at 01:23
  • The right answer to this is, as always, that you should **not** be manipulating the popup elements directly. Your popup should be represented in code behind by a view model, containing properties you want control over, bound to the popup properties as appropriate. Then you just change the properties in the view model, and they automatically get reflected in the popup itself. – Peter Duniho Apr 26 '17 at 02:20
  • This is my first time using WPF. I only started learning it for this project and we are on Sprint 2. I'm really not sure how to do what either of you are suggesting, or even what you are suggesting exactly. – Jonathan Higgs Apr 26 '17 at 16:51
  • You should start by reviewing available tutorials on the use of MVVM in WPF. For asking questions here on Stack Overflow, you should start by reading [mcve] and [ask]. Be sure to read also the articles linked at the bottom of that latter page. – Peter Duniho Apr 26 '17 at 18:02
  • I did not know of the existence of those tutorials, thank you for notifying me Peter. I figured out the solution to my problem is I'm stupid, so that's always nice. EDIT: That is, I was always able to edit those elements, just not in the way I was assuming I had to. – Jonathan Higgs Apr 26 '17 at 21:28

1 Answers1

0

Use x:Name instead of Name. Then you will be able to access the element in the code behind. See In WPF, what are the differences between the x:Name and Name attributes? for an explanation.

Community
  • 1
  • 1
AQuirky
  • 4,691
  • 2
  • 32
  • 51
  • As the answer to the question you reference explains, the `Name` attribute is mapped to `x:Name`, and will generate the field, if appropriate (e.g. it won't if the element is in a template, because there's no actual single instance of the element in that case). How does your answer actually fix the OP's code? Did you test it? Have you verified that it addresses their question? – Peter Duniho Apr 26 '17 at 02:35
  • It fixes the OP's code by allowing access to the button in the popup in the code behind. Indeed I tested it. Indeed I have verified it. There is nothing in the OP's question about a template. The popup as I interpreted it is defined in at the Window. There is no need to have a separate popup for each list item. – AQuirky Apr 26 '17 at 17:52
  • I'm surprised you were able to test your proposal in the context of the OP's code. Since they did not provide an actual [mcve] to test with. And I still don't see, given that in this context, both `Name` and `x:Name` will generate a field in the code-behind, how your proposal to use the latter instead of the former addresses the question. – Peter Duniho Apr 26 '17 at 18:01
  • Indeed perhaps the OP should have provided more code. Thus I had to make some assumptions about how the popup was implemented. But that does not diminish the fact that my answer will very likely solve his problem. Why are you beating me up about this? Why don't you write some code to prove that my answer does *not* work? – AQuirky Apr 26 '17 at 18:19
  • _"that does not diminish the fact that my answer will very likely solve his problem"_ -- an odd thing to claim, given that there's no difference between using `Name` and using `x:Name`. How _could_ your answer solve his problem? _"Why are you beating me up about this?"_ -- sorry, it's not my intent for you to feel "beaten". It _is_ my intent to ensure that answers posted are useful and solve problems. I don't see how yours possibly could meet that standard. _"Why don't you write some code to prove that my answer does not work?"_ -- because the original question doesn't have enough context. – Peter Duniho Apr 26 '17 at 18:23
  • In other words, you posted an answer without having any actual knowledge of what is wrong with the OP's code, and your suggestion doesn't make any material change in the code-behind. Assuming the use of `x:Name` would produce fields in the code-behind named "ConflictText" and "Detail_AddCourse", so too would the use of `Name`, just as the OP already has in their XAML. – Peter Duniho Apr 26 '17 at 18:25
  • I figured out the solution to my problem is I'm stupid, so that's always nice. I was always able to edit the elements using the Name property, just not in the way I was assuming I had to. – Jonathan Higgs Apr 26 '17 at 21:29